├── .cowcoin ├── .github └── ISSUE_TEMPLATE │ └── issue-template.md ├── .gitignore ├── LICENSE ├── NOTICE ├── README.md ├── compatible_hackrf_bladerf_lib.txt ├── doc ├── BLE_sniffer_guide.pdf ├── README.md ├── TI-BLE-INTRODUCTION.pdf └── ibeacon.pdf ├── host ├── CMakeLists.txt ├── btle-tools │ ├── 52-hackrf.rules │ ├── CMakeLists.txt │ ├── include │ │ └── common.h.in │ └── src │ │ ├── CMakeLists.txt │ │ ├── btle_rx.c │ │ ├── btle_tx.c │ │ ├── gauss_cos_sin_table.h │ │ ├── packets.txt │ │ ├── packets_discovery.txt │ │ ├── packets_ibeacon.txt │ │ ├── scramble_table.h │ │ └── scramble_table_ch37.h └── cmake │ ├── cmake_uninstall.cmake.in │ └── modules │ ├── FindLIBBLADERF.cmake │ ├── FindLIBHACKRF.cmake │ ├── FindThreads.cmake │ └── FindUSB1.cmake ├── matlab ├── get_number.m ├── get_number1.m ├── get_signal_from_hackrf_bin.m ├── sample_iq_4msps.txt ├── save_int_var_for_c.m ├── save_int_var_for_c_2d.m ├── scramble_gen.m ├── test_btle_rx.m ├── test_fixed_point.m ├── test_float_point.m └── test_scramble_gen_all_channel.m ├── open_btle_baseband_chip ├── README.md ├── architecture.png ├── btle-principle.png ├── btle-python-verilog-waveform.png ├── btle-top-openlane-detailed-placement-cts.png ├── btle_controller_xilinx_7z020.jpg ├── btle_rx_core-openlane-GDSII.png ├── open_btle_baseband_chip.ipynb ├── open_btle_baseband_chip.md ├── open_btle_baseband_chip_21_1.png ├── open_btle_baseband_chip_23_1.png ├── py-fig0.png ├── py-fig1.png ├── py-fig3.png └── py-fig4.png ├── python ├── backup_script.py ├── btlelib.py ├── test_alignment_with_btle_sdr.py ├── test_btle_ber.py └── test_vector_for_btle_verilog.py ├── usrp_replay_example ├── IQ_sample_for_matlab.txt ├── README.md ├── btle_ch37_iq_float32_welcom_msg.bin ├── gen_float32_bin_for_usrp_replay.m ├── replay_for_btle_4Msps.grc └── welcom_packets_discovery.txt └── verilog ├── bit_repeat_upsample.v ├── bit_repeat_upsample_tb.v ├── bit_repeat_upsample_test_input.txt ├── btle_controller.tcl ├── btle_controller.v ├── btle_controller_tb.v ├── btle_controller_wrapper.v ├── btle_controller_wrapper.xdc ├── btle_ll.v ├── btle_phy.v ├── btle_rx.v ├── btle_rx_core.v ├── btle_rx_core_tb.v ├── btle_rx_tb.v ├── btle_tx.v ├── btle_tx_tb.v ├── crc24.v ├── crc24_core.v ├── crc24_tb.v ├── dpram.v ├── gauss_filter.v ├── gauss_filter_tb.v ├── gfsk_demodulation.v ├── gfsk_demodulation_tb.v ├── gfsk_modulation.v ├── rx_clk_gen.v ├── scramble.v ├── scramble_core.v ├── scramble_tb.v ├── search_unique_bit_sequence.v ├── search_unique_bit_sequence_tb.v ├── serial_in_ram_out.v ├── tx_clk_gen.v ├── uart_frame_rx.v ├── uart_frame_tx.v ├── vco.v └── vco_tb.v /.cowcoin: -------------------------------------------------------------------------------- 1 | 0x8BD142A470A460C1E9f35AC30Bc546737346CeA4 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/issue-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: issue template 3 | about: Please report issue via this template 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 0. Who are you? 11 | 12 | 1. What is your own modification (if any)? 13 | 14 | 2. Environments: OS type/version, BTLE repo branch and commit revision 15 | 16 | 3. Board/hardware type 17 | 18 | 4. Detailed commands/steps to reproduce the issue, and the related error message, screenshot, etc 19 | 20 | 5. Your debug efforts and results (if any) 21 | 22 | 6. Any other thing we need to know for helping you better? 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | host/build 2 | 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | Copyright 2014-2024 Xianjun Jiao (putaoshu@msn.com) 179 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | BTLE 2 | Copyright 2014-2024 Xianjun Jiao 3 | 4 | This product includes software developed by Xianjun Jiao (putaoshu@msn.com) 5 | -------------------------------------------------------------------------------- /compatible_hackrf_bladerf_lib.txt: -------------------------------------------------------------------------------- 1 | Following versions were tested. Not means other versions won't work. 2 | 3 | bladeRF: 4 | 5 | bladeRF-cli --version 6 | 1.8.0-0.2019.07-5 7 | 8 | HackRF: 9 | 10 | hackrf_info 11 | hackrf_info version: git-f202160 12 | libhackrf version: git-f202160 (0.5) 13 | -------------------------------------------------------------------------------- /doc/BLE_sniffer_guide.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaoXianjun/BTLE/d431f70e4741b8f0e83c8d0ee50d14a5e5e6e63e/doc/BLE_sniffer_guide.pdf -------------------------------------------------------------------------------- /doc/README.md: -------------------------------------------------------------------------------- 1 | See some docs which are useful in [https://github.com/JiaoXianjun/doc](https://github.com/JiaoXianjun/doc) 2 | 3 | See new type of discovery packet in host/btle-tools/src/packets_discovery.txt 4 | 5 | 6 | -------------------------------------------------------------------------------- /doc/TI-BLE-INTRODUCTION.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaoXianjun/BTLE/d431f70e4741b8f0e83c8d0ee50d14a5e5e6e63e/doc/TI-BLE-INTRODUCTION.pdf -------------------------------------------------------------------------------- /doc/ibeacon.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaoXianjun/BTLE/d431f70e4741b8f0e83c8d0ee50d14a5e5e6e63e/doc/ibeacon.pdf -------------------------------------------------------------------------------- /host/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #top dir cmake project 2 | 3 | cmake_minimum_required(VERSION 2.8) 4 | project (btle_all) 5 | 6 | add_subdirectory(btle-tools) 7 | 8 | ######################################################################## 9 | # Create uninstall target 10 | ######################################################################## 11 | 12 | configure_file( 13 | ${PROJECT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in 14 | ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake 15 | @ONLY) 16 | 17 | 18 | add_custom_target(uninstall 19 | ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake 20 | ) 21 | -------------------------------------------------------------------------------- /host/btle-tools/52-hackrf.rules: -------------------------------------------------------------------------------- 1 | ATTR{idVendor}=="1d50", ATTR{idProduct}=="604b", SYMLINK+="hackrf-jawbreaker-%k", MODE="660", GROUP="plugdev" 2 | ATTR{idVendor}=="1d50", ATTR{idProduct}=="6089", SYMLINK+="hackrf-one-%k", MODE="660", GROUP="plugdev" 3 | ATTR{idVendor}=="1fc9", ATTR{idProduct}=="000c", SYMLINK+="nxp-dfu-%k", MODE="660", GROUP="plugdev" 4 | -------------------------------------------------------------------------------- /host/btle-tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2012 Jared Boone 2 | # Copyright 2013 Benjamin Vernoux 3 | # 4 | # This file is part of HackRF and bladeRF 5 | # 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2, or (at your option) 9 | # any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; see the file COPYING. If not, write to 18 | # the Free Software Foundation, Inc., 51 Franklin Street, 19 | # Boston, MA 02110-1301, USA. 20 | # 21 | 22 | # Based heavily upon the libftdi cmake setup. 23 | 24 | cmake_minimum_required(VERSION 2.8) 25 | project(btle-tools C) 26 | set(MAJOR_VERSION 0) 27 | set(MINOR_VERSION 5) 28 | set(PACKAGE btle-tools) 29 | set(VERSION_STRING ${MAJOR_VERSION}.${MINOR_VERSION}) 30 | set(VERSION ${VERSION_STRING}) 31 | set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../cmake/modules) 32 | 33 | if(MSVC) 34 | # include_directories(getopt) 35 | add_definitions(/D _CRT_SECURE_NO_WARNINGS) 36 | else() 37 | add_definitions(-Wall) 38 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu90") 39 | endif() 40 | 41 | # Find needed packages. 42 | IF (USE_BLADERF MATCHES 1) 43 | MESSAGE(STATUS "Use BLADERF") 44 | find_package(LIBBLADERF REQUIRED) 45 | include_directories(${LIBBLADERF_INCLUDE_DIR}) 46 | set(USE_RFBOARD "USE_BLADERF") 47 | ELSE (USE_BLADERF MATCHES 1) 48 | MESSAGE(STATUS "Use HACKRF") 49 | find_package(LIBHACKRF REQUIRED) 50 | include_directories(${LIBHACKRF_INCLUDE_DIR}) 51 | set(USE_RFBOARD "USE_HACKRF") 52 | ENDIF (USE_BLADERF MATCHES 1) 53 | 54 | CONFIGURE_FILE ( 55 | "${PROJECT_SOURCE_DIR}/include/common.h.in" 56 | "${PROJECT_SOURCE_DIR}/src/common.h" 57 | ) 58 | 59 | add_subdirectory(src) 60 | 61 | ######################################################################## 62 | # Create uninstall target 63 | ######################################################################## 64 | 65 | if(NOT btle_all_SOURCE_DIR) 66 | configure_file( 67 | ${PROJECT_SOURCE_DIR}/../cmake/cmake_uninstall.cmake.in 68 | ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake 69 | @ONLY) 70 | 71 | 72 | add_custom_target(uninstall 73 | ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake 74 | ) 75 | endif() 76 | 77 | ######################################################################## 78 | # Install udev rules 79 | ######################################################################## 80 | option(INSTALL_UDEV_RULES "Install udev rules for HackRF" OFF) 81 | if (INSTALL_UDEV_RULES) 82 | install ( 83 | FILES 52-hackrf.rules 84 | DESTINATION "/etc/udev/rules.d" 85 | COMPONENT "udev" 86 | ) 87 | else (INSTALL_UDEV_RULES) 88 | message (STATUS "Udev rules not being installed, install them with -DINSTALL_UDEV_RULES=ON") 89 | endif (INSTALL_UDEV_RULES) 90 | -------------------------------------------------------------------------------- /host/btle-tools/include/common.h.in: -------------------------------------------------------------------------------- 1 | #ifndef HAVE_COMMON_H 2 | #define HAVE_COMMON_H 3 | 4 | #define @USE_RFBOARD@ 5 | 6 | #endif 7 | 8 | -------------------------------------------------------------------------------- /host/btle-tools/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2012 Jared Boone 2 | # Copyright 2013 Benjamin Vernoux 3 | # 4 | # This file is part of HackRF and BladeRF. 5 | # 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2, or (at your option) 9 | # any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; see the file COPYING. If not, write to 18 | # the Free Software Foundation, Inc., 51 Franklin Street, 19 | # Boston, MA 02110-1301, USA. 20 | # 21 | 22 | # Based heavily upon the libftdi cmake setup. 23 | set(INSTALL_DEFAULT_BINDIR "bin" CACHE STRING "Appended to CMAKE_INSTALL_PREFIX") 24 | 25 | if(MSVC) 26 | add_library(libgetopt_static STATIC 27 | ../getopt/getopt.c 28 | ) 29 | endif() 30 | 31 | add_executable(btle_tx btle_tx.c) 32 | install(TARGETS btle_tx RUNTIME DESTINATION ${INSTALL_DEFAULT_BINDIR}) 33 | 34 | add_executable(btle_rx btle_rx.c) 35 | install(TARGETS btle_rx RUNTIME DESTINATION ${INSTALL_DEFAULT_BINDIR}) 36 | 37 | IF (USE_BLADERF MATCHES 1) 38 | include_directories(${LIBBLADERF_INCLUDE_DIR}) 39 | LIST(APPEND TOOLS_LINK_LIBS ${LIBBLADERF_LIBRARIES}) 40 | ELSE (USE_BLADERF MATCHES 1) 41 | include_directories(${LIBHACKRF_INCLUDE_DIR}) 42 | LIST(APPEND TOOLS_LINK_LIBS ${LIBHACKRF_LIBRARIES}) 43 | ENDIF (USE_BLADERF MATCHES 1) 44 | 45 | IF(NOT DEFINED C_INLINE) 46 | ADD_DEFINITIONS("-Dinline=") 47 | ENDIF(NOT DEFINED C_INLINE) 48 | 49 | if(MSVC) 50 | LIST(APPEND TOOLS_LINK_LIBS libgetopt_static) 51 | endif() 52 | 53 | target_link_libraries(btle_tx ${TOOLS_LINK_LIBS} m) 54 | 55 | IF (USE_BLADERF MATCHES 1) 56 | target_link_libraries(btle_rx ${TOOLS_LINK_LIBS} m -lpthread) 57 | ELSE (USE_BLADERF MATCHES 1) 58 | target_link_libraries(btle_rx ${TOOLS_LINK_LIBS} m) 59 | ENDIF (USE_BLADERF MATCHES 1) 60 | 61 | # MESSAGE(STATUS "1") 62 | # MESSAGE(STATUS ${LIBBLADERF_LIBRARIES}) 63 | # MESSAGE(STATUS "2") 64 | -------------------------------------------------------------------------------- /host/btle-tools/src/gauss_cos_sin_table.h: -------------------------------------------------------------------------------- 1 | // Lookup table to speedup the program 2 | // Xianjun Jiao (putaoshu@msn.com) 3 | 4 | const int8_t gauss_coef_int8[16] = { 5 | 0, 0, 0, 0, 2, 11, 32, 53, 60, 53, 32, 11, 2, 0, 0, 0, }; 6 | 7 | const int8_t cos_table_int8[1024] = { 8 | 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 126, 126, 126, 126, 126, 126, 126, 126, 126, 9 | 126, 126, 125, 125, 125, 125, 125, 125, 125, 124, 124, 124, 124, 124, 124, 123, 123, 123, 123, 123, 122, 122, 122, 122, 10 | 122, 121, 121, 121, 121, 120, 120, 120, 120, 119, 119, 119, 118, 118, 118, 118, 117, 117, 117, 116, 116, 116, 115, 115, 11 | 115, 114, 114, 114, 113, 113, 113, 112, 112, 112, 111, 111, 111, 110, 110, 109, 109, 109, 108, 108, 107, 107, 106, 106, 12 | 106, 105, 105, 104, 104, 103, 103, 102, 102, 102, 101, 101, 100, 100, 99, 99, 98, 98, 97, 97, 96, 96, 95, 95, 13 | 94, 94, 93, 93, 92, 91, 91, 90, 90, 89, 89, 88, 88, 87, 86, 86, 85, 85, 84, 84, 83, 82, 82, 81, 14 | 81, 80, 79, 79, 78, 78, 77, 76, 76, 75, 74, 74, 73, 72, 72, 71, 71, 70, 69, 69, 68, 67, 67, 66, 15 | 65, 65, 64, 63, 63, 62, 61, 61, 60, 59, 58, 58, 57, 56, 56, 55, 54, 54, 53, 52, 51, 51, 50, 49, 16 | 49, 48, 47, 46, 46, 45, 44, 44, 43, 42, 41, 41, 40, 39, 38, 38, 37, 36, 35, 35, 34, 33, 32, 32, 17 | 31, 30, 29, 29, 28, 27, 26, 26, 25, 24, 23, 22, 22, 21, 20, 19, 19, 18, 17, 16, 16, 15, 14, 13, 18 | 12, 12, 11, 10, 9, 9, 8, 7, 6, 5, 5, 4, 3, 2, 2, 1, 0, -1, -2, -2, -3, -4, -5, -5, 19 | -6, -7, -8, -9, -9, -10, -11, -12, -12, -13, -14, -15, -16, -16, -17, -18, -19, -19, -20, -21, -22, -22, -23, -24, 20 | -25, -26, -26, -27, -28, -29, -29, -30, -31, -32, -32, -33, -34, -35, -35, -36, -37, -38, -38, -39, -40, -41, -41, -42, 21 | -43, -44, -44, -45, -46, -46, -47, -48, -49, -49, -50, -51, -51, -52, -53, -54, -54, -55, -56, -56, -57, -58, -58, -59, 22 | -60, -61, -61, -62, -63, -63, -64, -65, -65, -66, -67, -67, -68, -69, -69, -70, -71, -71, -72, -72, -73, -74, -74, -75, 23 | -76, -76, -77, -78, -78, -79, -79, -80, -81, -81, -82, -82, -83, -84, -84, -85, -85, -86, -86, -87, -88, -88, -89, -89, 24 | -90, -90, -91, -91, -92, -93, -93, -94, -94, -95, -95, -96, -96, -97, -97, -98, -98, -99, -99, -100, -100, -101, -101, -102, 25 | -102, -102, -103, -103, -104, -104, -105, -105, -106, -106, -106, -107, -107, -108, -108, -109, -109, -109, -110, -110, -111, -111, -111, -112, 26 | -112, -112, -113, -113, -113, -114, -114, -114, -115, -115, -115, -116, -116, -116, -117, -117, -117, -118, -118, -118, -118, -119, -119, -119, 27 | -120, -120, -120, -120, -121, -121, -121, -121, -122, -122, -122, -122, -122, -123, -123, -123, -123, -123, -124, -124, -124, -124, -124, -124, 28 | -125, -125, -125, -125, -125, -125, -125, -126, -126, -126, -126, -126, -126, -126, -126, -126, -126, -126, -127, -127, -127, -127, -127, -127, 29 | -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -126, 30 | -126, -126, -126, -126, -126, -126, -126, -126, -126, -126, -125, -125, -125, -125, -125, -125, -125, -124, -124, -124, -124, -124, -124, -123, 31 | -123, -123, -123, -123, -122, -122, -122, -122, -122, -121, -121, -121, -121, -120, -120, -120, -120, -119, -119, -119, -118, -118, -118, -118, 32 | -117, -117, -117, -116, -116, -116, -115, -115, -115, -114, -114, -114, -113, -113, -113, -112, -112, -112, -111, -111, -111, -110, -110, -109, 33 | -109, -109, -108, -108, -107, -107, -106, -106, -106, -105, -105, -104, -104, -103, -103, -102, -102, -102, -101, -101, -100, -100, -99, -99, 34 | -98, -98, -97, -97, -96, -96, -95, -95, -94, -94, -93, -93, -92, -91, -91, -90, -90, -89, -89, -88, -88, -87, -86, -86, 35 | -85, -85, -84, -84, -83, -82, -82, -81, -81, -80, -79, -79, -78, -78, -77, -76, -76, -75, -74, -74, -73, -72, -72, -71, 36 | -71, -70, -69, -69, -68, -67, -67, -66, -65, -65, -64, -63, -63, -62, -61, -61, -60, -59, -58, -58, -57, -56, -56, -55, 37 | -54, -54, -53, -52, -51, -51, -50, -49, -49, -48, -47, -46, -46, -45, -44, -44, -43, -42, -41, -41, -40, -39, -38, -38, 38 | -37, -36, -35, -35, -34, -33, -32, -32, -31, -30, -29, -29, -28, -27, -26, -26, -25, -24, -23, -22, -22, -21, -20, -19, 39 | -19, -18, -17, -16, -16, -15, -14, -13, -12, -12, -11, -10, -9, -9, -8, -7, -6, -5, -5, -4, -3, -2, -2, -1, 40 | 0, 1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15, 16, 16, 17, 18, 41 | 19, 19, 20, 21, 22, 22, 23, 24, 25, 26, 26, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36, 42 | 37, 38, 38, 39, 40, 41, 41, 42, 43, 44, 44, 45, 46, 46, 47, 48, 49, 49, 50, 51, 51, 52, 53, 54, 43 | 54, 55, 56, 56, 57, 58, 58, 59, 60, 61, 61, 62, 63, 63, 64, 65, 65, 66, 67, 67, 68, 69, 69, 70, 44 | 71, 71, 72, 72, 73, 74, 74, 75, 76, 76, 77, 78, 78, 79, 79, 80, 81, 81, 82, 82, 83, 84, 84, 85, 45 | 85, 86, 86, 87, 88, 88, 89, 89, 90, 90, 91, 91, 92, 93, 93, 94, 94, 95, 95, 96, 96, 97, 97, 98, 46 | 98, 99, 99, 100, 100, 101, 101, 102, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 106, 107, 107, 108, 108, 109, 47 | 109, 109, 110, 110, 111, 111, 111, 112, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115, 115, 116, 116, 116, 117, 117, 48 | 117, 118, 118, 118, 118, 119, 119, 119, 120, 120, 120, 120, 121, 121, 121, 121, 122, 122, 122, 122, 122, 123, 123, 123, 49 | 123, 123, 124, 124, 124, 124, 124, 124, 125, 125, 125, 125, 125, 125, 125, 126, 126, 126, 126, 126, 126, 126, 126, 126, 50 | 126, 126, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, }; 51 | 52 | const int8_t sin_table_int8[1024] = { 53 | 0, 1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15, 16, 16, 17, 18, 54 | 19, 19, 20, 21, 22, 22, 23, 24, 25, 26, 26, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36, 55 | 37, 38, 38, 39, 40, 41, 41, 42, 43, 44, 44, 45, 46, 46, 47, 48, 49, 49, 50, 51, 51, 52, 53, 54, 56 | 54, 55, 56, 56, 57, 58, 58, 59, 60, 61, 61, 62, 63, 63, 64, 65, 65, 66, 67, 67, 68, 69, 69, 70, 57 | 71, 71, 72, 72, 73, 74, 74, 75, 76, 76, 77, 78, 78, 79, 79, 80, 81, 81, 82, 82, 83, 84, 84, 85, 58 | 85, 86, 86, 87, 88, 88, 89, 89, 90, 90, 91, 91, 92, 93, 93, 94, 94, 95, 95, 96, 96, 97, 97, 98, 59 | 98, 99, 99, 100, 100, 101, 101, 102, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 106, 107, 107, 108, 108, 109, 60 | 109, 109, 110, 110, 111, 111, 111, 112, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115, 115, 116, 116, 116, 117, 117, 61 | 117, 118, 118, 118, 118, 119, 119, 119, 120, 120, 120, 120, 121, 121, 121, 121, 122, 122, 122, 122, 122, 123, 123, 123, 62 | 123, 123, 124, 124, 124, 124, 124, 124, 125, 125, 125, 125, 125, 125, 125, 126, 126, 126, 126, 126, 126, 126, 126, 126, 63 | 126, 126, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 64 | 127, 127, 127, 127, 127, 127, 127, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 125, 125, 125, 125, 125, 125, 65 | 125, 124, 124, 124, 124, 124, 124, 123, 123, 123, 123, 123, 122, 122, 122, 122, 122, 121, 121, 121, 121, 120, 120, 120, 66 | 120, 119, 119, 119, 118, 118, 118, 118, 117, 117, 117, 116, 116, 116, 115, 115, 115, 114, 114, 114, 113, 113, 113, 112, 67 | 112, 112, 111, 111, 111, 110, 110, 109, 109, 109, 108, 108, 107, 107, 106, 106, 106, 105, 105, 104, 104, 103, 103, 102, 68 | 102, 102, 101, 101, 100, 100, 99, 99, 98, 98, 97, 97, 96, 96, 95, 95, 94, 94, 93, 93, 92, 91, 91, 90, 69 | 90, 89, 89, 88, 88, 87, 86, 86, 85, 85, 84, 84, 83, 82, 82, 81, 81, 80, 79, 79, 78, 78, 77, 76, 70 | 76, 75, 74, 74, 73, 72, 72, 71, 71, 70, 69, 69, 68, 67, 67, 66, 65, 65, 64, 63, 63, 62, 61, 61, 71 | 60, 59, 58, 58, 57, 56, 56, 55, 54, 54, 53, 52, 51, 51, 50, 49, 49, 48, 47, 46, 46, 45, 44, 44, 72 | 43, 42, 41, 41, 40, 39, 38, 38, 37, 36, 35, 35, 34, 33, 32, 32, 31, 30, 29, 29, 28, 27, 26, 26, 73 | 25, 24, 23, 22, 22, 21, 20, 19, 19, 18, 17, 16, 16, 15, 14, 13, 12, 12, 11, 10, 9, 9, 8, 7, 74 | 6, 5, 5, 4, 3, 2, 2, 1, 0, -1, -2, -2, -3, -4, -5, -5, -6, -7, -8, -9, -9, -10, -11, -12, 75 | -12, -13, -14, -15, -16, -16, -17, -18, -19, -19, -20, -21, -22, -22, -23, -24, -25, -26, -26, -27, -28, -29, -29, -30, 76 | -31, -32, -32, -33, -34, -35, -35, -36, -37, -38, -38, -39, -40, -41, -41, -42, -43, -44, -44, -45, -46, -46, -47, -48, 77 | -49, -49, -50, -51, -51, -52, -53, -54, -54, -55, -56, -56, -57, -58, -58, -59, -60, -61, -61, -62, -63, -63, -64, -65, 78 | -65, -66, -67, -67, -68, -69, -69, -70, -71, -71, -72, -72, -73, -74, -74, -75, -76, -76, -77, -78, -78, -79, -79, -80, 79 | -81, -81, -82, -82, -83, -84, -84, -85, -85, -86, -86, -87, -88, -88, -89, -89, -90, -90, -91, -91, -92, -93, -93, -94, 80 | -94, -95, -95, -96, -96, -97, -97, -98, -98, -99, -99, -100, -100, -101, -101, -102, -102, -102, -103, -103, -104, -104, -105, -105, 81 | -106, -106, -106, -107, -107, -108, -108, -109, -109, -109, -110, -110, -111, -111, -111, -112, -112, -112, -113, -113, -113, -114, -114, -114, 82 | -115, -115, -115, -116, -116, -116, -117, -117, -117, -118, -118, -118, -118, -119, -119, -119, -120, -120, -120, -120, -121, -121, -121, -121, 83 | -122, -122, -122, -122, -122, -123, -123, -123, -123, -123, -124, -124, -124, -124, -124, -124, -125, -125, -125, -125, -125, -125, -125, -126, 84 | -126, -126, -126, -126, -126, -126, -126, -126, -126, -126, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, 85 | -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -127, -126, -126, -126, -126, -126, -126, -126, -126, -126, 86 | -126, -126, -125, -125, -125, -125, -125, -125, -125, -124, -124, -124, -124, -124, -124, -123, -123, -123, -123, -123, -122, -122, -122, -122, 87 | -122, -121, -121, -121, -121, -120, -120, -120, -120, -119, -119, -119, -118, -118, -118, -118, -117, -117, -117, -116, -116, -116, -115, -115, 88 | -115, -114, -114, -114, -113, -113, -113, -112, -112, -112, -111, -111, -111, -110, -110, -109, -109, -109, -108, -108, -107, -107, -106, -106, 89 | -106, -105, -105, -104, -104, -103, -103, -102, -102, -102, -101, -101, -100, -100, -99, -99, -98, -98, -97, -97, -96, -96, -95, -95, 90 | -94, -94, -93, -93, -92, -91, -91, -90, -90, -89, -89, -88, -88, -87, -86, -86, -85, -85, -84, -84, -83, -82, -82, -81, 91 | -81, -80, -79, -79, -78, -78, -77, -76, -76, -75, -74, -74, -73, -72, -72, -71, -71, -70, -69, -69, -68, -67, -67, -66, 92 | -65, -65, -64, -63, -63, -62, -61, -61, -60, -59, -58, -58, -57, -56, -56, -55, -54, -54, -53, -52, -51, -51, -50, -49, 93 | -49, -48, -47, -46, -46, -45, -44, -44, -43, -42, -41, -41, -40, -39, -38, -38, -37, -36, -35, -35, -34, -33, -32, -32, 94 | -31, -30, -29, -29, -28, -27, -26, -26, -25, -24, -23, -22, -22, -21, -20, -19, -19, -18, -17, -16, -16, -15, -14, -13, 95 | -12, -12, -11, -10, -9, -9, -8, -7, -6, -5, -5, -4, -3, -2, -2, -1, }; 96 | 97 | -------------------------------------------------------------------------------- /host/btle-tools/src/packets.txt: -------------------------------------------------------------------------------- 1 | # Simulate BTLE Connection establishment according to BTLE/doc/TI-BLE-INTRODUCTION.pdf 2 | # Turn on your BLE sniffer dongle at channel 37 to see the procedure 3 | 4 | 37-ADV_IND-TxAdd-0-RxAdd-0-AdvA-90D7EBB19299-AdvData-0201050702031802180418-Space-1000 5 | 6 | 37-CONNECT_REQ-TxAdd-0-RxAdd-0-InitA-001830EA965F-AdvA-90D7EBB19299-AA-60850A1B-CRCInit-A77B22-WinSize-02-WinOffset-000F-Interval-0050-Latency-0000-Timeout-07D0-ChM-1FFFFFFFFF-Hop-9-SCA-5-Space-1000 7 | 8 | 9-LL_DATA-AA-60850A1B-LLID-1-NESN-0-SN-0-MD-0-DATA-X-CRCInit-A77B22-Space-1000 9 | 10 | r1 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /host/btle-tools/src/packets_discovery.txt: -------------------------------------------------------------------------------- 1 | # example 2 | # ./btle_tx 37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040506-FLAGS-02-LOCAL_NAME09-CA-TXPOWER-03-SERVICE03-180D1810-SERVICE_DATA-180D40-MANUF_DATA-0001FF-CONN_INTERVAL-0006 (-SERVICE_SOLI14-1811) 3 | # FLAGS: 0x01 LE Limited Discoverable Mode; 0x02 LE General Discoverable Mode 4 | # SERVICE: 5 | # 0x02 16-bit Service UUIDs More 16-bit UUIDs available 6 | # 0x03 16-bit Service UUIDs Complete list of 16-bit UUIDs available 7 | # 0x04 32-bit Service UUIDs More 32-bit UUIDs available 8 | # 0x05 32-bit Service UUIDs Complete list of 32-bit UUIDs available 9 | # 0x06 128-bit Service UUIDs More 128-bit UUIDs available 10 | # 0x07 128-bit Service UUIDs Complete list of 128-bit UUIDs available 11 | 12 | # 37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040506-FLAGS-02-LOCAL_NAME09-Jxj-TXPOWER-03-SERVICE03-180D1810-SERVICE_DATA-180D40-MANUF_DATA-004CFF-CONN_INTERVAL-0006 13 | 14 | # r30 15 | 16 | 37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040506-LOCAL_NAME09-SDR Bluetooth Low Energy 17 | 18 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040500-LOCAL_NAME09-CA0000 11950 22.626 113.823 1 19 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040501-LOCAL_NAME09-CA0001 11950 22.626 113.823 1 20 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040502-LOCAL_NAME09-CA0002 11950 22.626 113.823 1 21 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040503-LOCAL_NAME09-CA0003 11950 22.626 113.823 1 22 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040504-LOCAL_NAME09-CA0004 11950 22.626 113.823 1 23 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040505-LOCAL_NAME09-CA0005 11950 22.626 113.823 1 24 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040506-LOCAL_NAME09-CA0006 11950 22.626 113.823 1 25 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040507-LOCAL_NAME09-CA0007 11950 22.626 113.823 1 26 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040508-LOCAL_NAME09-CA0008 11950 22.626 113.823 1 27 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040509-LOCAL_NAME09-CA0009 11950 22.626 113.823 1 28 | 29 | r4000 30 | 31 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040506-LOCAL_NAME09-01234567890123456789012345678 32 | 33 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040506-FLAGS-02-LOCAL_NAME09-01234567890123456789012345 34 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-110203040506-FLAGS-02-LOCAL_NAME09-11234567890123456789012345 35 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-210203040506-FLAGS-02-LOCAL_NAME09-21234567890123456789012345 36 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-310203040506-FLAGS-02-LOCAL_NAME09-31234567890123456789012345 37 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-410203040506-FLAGS-02-LOCAL_NAME09-41234567890123456789012345 38 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-510203040506-FLAGS-02-LOCAL_NAME09-51234567890123456789012345 39 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-610203040506-FLAGS-02-LOCAL_NAME09-61234567890123456789012345 40 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-710203040506-FLAGS-02-LOCAL_NAME09-71234567890123456789012345 41 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-810203040506-FLAGS-02-LOCAL_NAME09-81234567890123456789012345 42 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-910203040506-FLAGS-02-LOCAL_NAME09-91234567890123456789012345 43 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-a10203040506-FLAGS-02-LOCAL_NAME09-a1234567890123456789012345 44 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-b10203040506-FLAGS-02-LOCAL_NAME09-b1234567890123456789012345 45 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-c10203040506-FLAGS-02-LOCAL_NAME09-c1234567890123456789012345 46 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-d10203040506-FLAGS-02-LOCAL_NAME09-d1234567890123456789012345 47 | 48 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040506-FLAGS-02-SERVICE03-180D-SERVICE_DATA-180D40-SPACE-500 49 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-110203040506-FLAGS-02-SERVICE03-1819-SERVICE_DATA-181940-SPACE-100 50 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-210203040506-FLAGS-02-SERVICE03-181c-SERVICE_DATA-181c40-SPACE-500 51 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-310203040506-FLAGS-02-SERVICE03-180a-SERVICE_DATA-180a40-SPACE-500 52 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-410203040506-FLAGS-02-SERVICE03-1800-SERVICE_DATA-180040-SPACE-500 53 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-410203040506-FLAGS-02-SERVICE03-1801-SERVICE_DATA-180140-SPACE-500 54 | # r30 55 | 56 | -------------------------------------------------------------------------------- /host/btle-tools/src/packets_ibeacon.txt: -------------------------------------------------------------------------------- 1 | 37-iBeacon-AdvA-010203040506-UUID-B9407F30F5F8466EAFF925556B57FE6D-Major-0008-Minor-0009-TxPower-C5-Space-100 2 | 3 | r10 4 | 5 | 6 | -------------------------------------------------------------------------------- /host/btle-tools/src/scramble_table.h: -------------------------------------------------------------------------------- 1 | // Scramble table definition 2 | // Xianjun Jiao (putaoshu@msn.com) 3 | 4 | const uint8_t scramble_table[40][42] = { 5 | {64, 178, 188, 195, 31, 55, 74, 95, 133, 246, 156, 154, 193, 214, 197, 68, 32, 89, 222, 225, 143, 27, 165, 175, 66, 123, 78, 205, 96, 235, 98, 34, 144, 44, 239, 240, 199, 141, 210, 87, 161, 61, }, 6 | {137, 64, 178, 188, 195, 31, 55, 74, 95, 133, 246, 156, 154, 193, 214, 197, 68, 32, 89, 222, 225, 143, 27, 165, 175, 66, 123, 78, 205, 96, 235, 98, 34, 144, 44, 239, 240, 199, 141, 210, 87, 161, }, 7 | {210, 87, 161, 61, 167, 102, 176, 117, 49, 17, 72, 150, 119, 248, 227, 70, 233, 171, 208, 158, 83, 51, 216, 186, 152, 8, 36, 203, 59, 252, 113, 163, 244, 85, 104, 207, 169, 25, 108, 93, 76, 4, }, 8 | {27, 165, 175, 66, 123, 78, 205, 96, 235, 98, 34, 144, 44, 239, 240, 199, 141, 210, 87, 161, 61, 167, 102, 176, 117, 49, 17, 72, 150, 119, 248, 227, 70, 233, 171, 208, 158, 83, 51, 216, 186, 152, }, 9 | {100, 121, 135, 63, 110, 148, 190, 10, 237, 57, 53, 131, 173, 139, 137, 64, 178, 188, 195, 31, 55, 74, 95, 133, 246, 156, 154, 193, 214, 197, 68, 32, 89, 222, 225, 143, 27, 165, 175, 66, 123, 78, }, 10 | {173, 139, 137, 64, 178, 188, 195, 31, 55, 74, 95, 133, 246, 156, 154, 193, 214, 197, 68, 32, 89, 222, 225, 143, 27, 165, 175, 66, 123, 78, 205, 96, 235, 98, 34, 144, 44, 239, 240, 199, 141, 210, }, 11 | {246, 156, 154, 193, 214, 197, 68, 32, 89, 222, 225, 143, 27, 165, 175, 66, 123, 78, 205, 96, 235, 98, 34, 144, 44, 239, 240, 199, 141, 210, 87, 161, 61, 167, 102, 176, 117, 49, 17, 72, 150, 119, }, 12 | {63, 110, 148, 190, 10, 237, 57, 53, 131, 173, 139, 137, 64, 178, 188, 195, 31, 55, 74, 95, 133, 246, 156, 154, 193, 214, 197, 68, 32, 89, 222, 225, 143, 27, 165, 175, 66, 123, 78, 205, 96, 235, }, 13 | {8, 36, 203, 59, 252, 113, 163, 244, 85, 104, 207, 169, 25, 108, 93, 76, 4, 146, 229, 29, 254, 184, 81, 250, 42, 180, 231, 212, 12, 182, 46, 38, 2, 201, 242, 14, 127, 220, 40, 125, 21, 218, }, 14 | {193, 214, 197, 68, 32, 89, 222, 225, 143, 27, 165, 175, 66, 123, 78, 205, 96, 235, 98, 34, 144, 44, 239, 240, 199, 141, 210, 87, 161, 61, 167, 102, 176, 117, 49, 17, 72, 150, 119, 248, 227, 70, }, 15 | {154, 193, 214, 197, 68, 32, 89, 222, 225, 143, 27, 165, 175, 66, 123, 78, 205, 96, 235, 98, 34, 144, 44, 239, 240, 199, 141, 210, 87, 161, 61, 167, 102, 176, 117, 49, 17, 72, 150, 119, 248, 227, }, 16 | {83, 51, 216, 186, 152, 8, 36, 203, 59, 252, 113, 163, 244, 85, 104, 207, 169, 25, 108, 93, 76, 4, 146, 229, 29, 254, 184, 81, 250, 42, 180, 231, 212, 12, 182, 46, 38, 2, 201, 242, 14, 127, }, 17 | {44, 239, 240, 199, 141, 210, 87, 161, 61, 167, 102, 176, 117, 49, 17, 72, 150, 119, 248, 227, 70, 233, 171, 208, 158, 83, 51, 216, 186, 152, 8, 36, 203, 59, 252, 113, 163, 244, 85, 104, 207, 169, }, 18 | {229, 29, 254, 184, 81, 250, 42, 180, 231, 212, 12, 182, 46, 38, 2, 201, 242, 14, 127, 220, 40, 125, 21, 218, 115, 106, 6, 91, 23, 19, 129, 100, 121, 135, 63, 110, 148, 190, 10, 237, 57, 53, }, 19 | {190, 10, 237, 57, 53, 131, 173, 139, 137, 64, 178, 188, 195, 31, 55, 74, 95, 133, 246, 156, 154, 193, 214, 197, 68, 32, 89, 222, 225, 143, 27, 165, 175, 66, 123, 78, 205, 96, 235, 98, 34, 144, }, 20 | {119, 248, 227, 70, 233, 171, 208, 158, 83, 51, 216, 186, 152, 8, 36, 203, 59, 252, 113, 163, 244, 85, 104, 207, 169, 25, 108, 93, 76, 4, 146, 229, 29, 254, 184, 81, 250, 42, 180, 231, 212, 12, }, 21 | {208, 158, 83, 51, 216, 186, 152, 8, 36, 203, 59, 252, 113, 163, 244, 85, 104, 207, 169, 25, 108, 93, 76, 4, 146, 229, 29, 254, 184, 81, 250, 42, 180, 231, 212, 12, 182, 46, 38, 2, 201, 242, }, 22 | {25, 108, 93, 76, 4, 146, 229, 29, 254, 184, 81, 250, 42, 180, 231, 212, 12, 182, 46, 38, 2, 201, 242, 14, 127, 220, 40, 125, 21, 218, 115, 106, 6, 91, 23, 19, 129, 100, 121, 135, 63, 110, }, 23 | {66, 123, 78, 205, 96, 235, 98, 34, 144, 44, 239, 240, 199, 141, 210, 87, 161, 61, 167, 102, 176, 117, 49, 17, 72, 150, 119, 248, 227, 70, 233, 171, 208, 158, 83, 51, 216, 186, 152, 8, 36, 203, }, 24 | {139, 137, 64, 178, 188, 195, 31, 55, 74, 95, 133, 246, 156, 154, 193, 214, 197, 68, 32, 89, 222, 225, 143, 27, 165, 175, 66, 123, 78, 205, 96, 235, 98, 34, 144, 44, 239, 240, 199, 141, 210, 87, }, 25 | {244, 85, 104, 207, 169, 25, 108, 93, 76, 4, 146, 229, 29, 254, 184, 81, 250, 42, 180, 231, 212, 12, 182, 46, 38, 2, 201, 242, 14, 127, 220, 40, 125, 21, 218, 115, 106, 6, 91, 23, 19, 129, }, 26 | {61, 167, 102, 176, 117, 49, 17, 72, 150, 119, 248, 227, 70, 233, 171, 208, 158, 83, 51, 216, 186, 152, 8, 36, 203, 59, 252, 113, 163, 244, 85, 104, 207, 169, 25, 108, 93, 76, 4, 146, 229, 29, }, 27 | {102, 176, 117, 49, 17, 72, 150, 119, 248, 227, 70, 233, 171, 208, 158, 83, 51, 216, 186, 152, 8, 36, 203, 59, 252, 113, 163, 244, 85, 104, 207, 169, 25, 108, 93, 76, 4, 146, 229, 29, 254, 184, }, 28 | {175, 66, 123, 78, 205, 96, 235, 98, 34, 144, 44, 239, 240, 199, 141, 210, 87, 161, 61, 167, 102, 176, 117, 49, 17, 72, 150, 119, 248, 227, 70, 233, 171, 208, 158, 83, 51, 216, 186, 152, 8, 36, }, 29 | {152, 8, 36, 203, 59, 252, 113, 163, 244, 85, 104, 207, 169, 25, 108, 93, 76, 4, 146, 229, 29, 254, 184, 81, 250, 42, 180, 231, 212, 12, 182, 46, 38, 2, 201, 242, 14, 127, 220, 40, 125, 21, }, 30 | {81, 250, 42, 180, 231, 212, 12, 182, 46, 38, 2, 201, 242, 14, 127, 220, 40, 125, 21, 218, 115, 106, 6, 91, 23, 19, 129, 100, 121, 135, 63, 110, 148, 190, 10, 237, 57, 53, 131, 173, 139, 137, }, 31 | {10, 237, 57, 53, 131, 173, 139, 137, 64, 178, 188, 195, 31, 55, 74, 95, 133, 246, 156, 154, 193, 214, 197, 68, 32, 89, 222, 225, 143, 27, 165, 175, 66, 123, 78, 205, 96, 235, 98, 34, 144, 44, }, 32 | {195, 31, 55, 74, 95, 133, 246, 156, 154, 193, 214, 197, 68, 32, 89, 222, 225, 143, 27, 165, 175, 66, 123, 78, 205, 96, 235, 98, 34, 144, 44, 239, 240, 199, 141, 210, 87, 161, 61, 167, 102, 176, }, 33 | {188, 195, 31, 55, 74, 95, 133, 246, 156, 154, 193, 214, 197, 68, 32, 89, 222, 225, 143, 27, 165, 175, 66, 123, 78, 205, 96, 235, 98, 34, 144, 44, 239, 240, 199, 141, 210, 87, 161, 61, 167, 102, }, 34 | {117, 49, 17, 72, 150, 119, 248, 227, 70, 233, 171, 208, 158, 83, 51, 216, 186, 152, 8, 36, 203, 59, 252, 113, 163, 244, 85, 104, 207, 169, 25, 108, 93, 76, 4, 146, 229, 29, 254, 184, 81, 250, }, 35 | {46, 38, 2, 201, 242, 14, 127, 220, 40, 125, 21, 218, 115, 106, 6, 91, 23, 19, 129, 100, 121, 135, 63, 110, 148, 190, 10, 237, 57, 53, 131, 173, 139, 137, 64, 178, 188, 195, 31, 55, 74, 95, }, 36 | {231, 212, 12, 182, 46, 38, 2, 201, 242, 14, 127, 220, 40, 125, 21, 218, 115, 106, 6, 91, 23, 19, 129, 100, 121, 135, 63, 110, 148, 190, 10, 237, 57, 53, 131, 173, 139, 137, 64, 178, 188, 195, }, 37 | {96, 235, 98, 34, 144, 44, 239, 240, 199, 141, 210, 87, 161, 61, 167, 102, 176, 117, 49, 17, 72, 150, 119, 248, 227, 70, 233, 171, 208, 158, 83, 51, 216, 186, 152, 8, 36, 203, 59, 252, 113, 163, }, 38 | {169, 25, 108, 93, 76, 4, 146, 229, 29, 254, 184, 81, 250, 42, 180, 231, 212, 12, 182, 46, 38, 2, 201, 242, 14, 127, 220, 40, 125, 21, 218, 115, 106, 6, 91, 23, 19, 129, 100, 121, 135, 63, }, 39 | {242, 14, 127, 220, 40, 125, 21, 218, 115, 106, 6, 91, 23, 19, 129, 100, 121, 135, 63, 110, 148, 190, 10, 237, 57, 53, 131, 173, 139, 137, 64, 178, 188, 195, 31, 55, 74, 95, 133, 246, 156, 154, }, 40 | {59, 252, 113, 163, 244, 85, 104, 207, 169, 25, 108, 93, 76, 4, 146, 229, 29, 254, 184, 81, 250, 42, 180, 231, 212, 12, 182, 46, 38, 2, 201, 242, 14, 127, 220, 40, 125, 21, 218, 115, 106, 6, }, 41 | {68, 32, 89, 222, 225, 143, 27, 165, 175, 66, 123, 78, 205, 96, 235, 98, 34, 144, 44, 239, 240, 199, 141, 210, 87, 161, 61, 167, 102, 176, 117, 49, 17, 72, 150, 119, 248, 227, 70, 233, 171, 208, }, 42 | {141, 210, 87, 161, 61, 167, 102, 176, 117, 49, 17, 72, 150, 119, 248, 227, 70, 233, 171, 208, 158, 83, 51, 216, 186, 152, 8, 36, 203, 59, 252, 113, 163, 244, 85, 104, 207, 169, 25, 108, 93, 76, }, 43 | {214, 197, 68, 32, 89, 222, 225, 143, 27, 165, 175, 66, 123, 78, 205, 96, 235, 98, 34, 144, 44, 239, 240, 199, 141, 210, 87, 161, 61, 167, 102, 176, 117, 49, 17, 72, 150, 119, 248, 227, 70, 233, }, 44 | {31, 55, 74, 95, 133, 246, 156, 154, 193, 214, 197, 68, 32, 89, 222, 225, 143, 27, 165, 175, 66, 123, 78, 205, 96, 235, 98, 34, 144, 44, 239, 240, 199, 141, 210, 87, 161, 61, 167, 102, 176, 117, }, 45 | }; 46 | 47 | -------------------------------------------------------------------------------- /host/btle-tools/src/scramble_table_ch37.h: -------------------------------------------------------------------------------- 1 | // Scramble table definition for channel 37 2 | // Xianjun Jiao (putaoshu@msn.com) 3 | 4 | const uint8_t scramble_table_ch37[42] = { 5 | 141, 210, 87, 161, 61, 167, 102, 176, 117, 49, 17, 72, 150, 119, 248, 227, 70, 233, 171, 208, 158, 83, 51, 216, 6 | 186, 152, 8, 36, 203, 59, 252, 113, 163, 244, 85, 104, 207, 169, 25, 108, 93, 76, }; 7 | 8 | -------------------------------------------------------------------------------- /host/cmake/cmake_uninstall.cmake.in: -------------------------------------------------------------------------------- 1 | # http://www.vtk.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F 2 | 3 | IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 4 | MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") 5 | ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 6 | 7 | FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) 8 | STRING(REGEX REPLACE "\n" ";" files "${files}") 9 | FOREACH(file ${files}) 10 | MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") 11 | IF(EXISTS "$ENV{DESTDIR}${file}") 12 | EXEC_PROGRAM( 13 | "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" 14 | OUTPUT_VARIABLE rm_out 15 | RETURN_VALUE rm_retval 16 | ) 17 | IF(NOT "${rm_retval}" STREQUAL 0) 18 | MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") 19 | ENDIF(NOT "${rm_retval}" STREQUAL 0) 20 | ELSEIF(IS_SYMLINK "$ENV{DESTDIR}${file}") 21 | EXEC_PROGRAM( 22 | "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" 23 | OUTPUT_VARIABLE rm_out 24 | RETURN_VALUE rm_retval 25 | ) 26 | IF(NOT "${rm_retval}" STREQUAL 0) 27 | MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") 28 | ENDIF(NOT "${rm_retval}" STREQUAL 0) 29 | ELSE(EXISTS "$ENV{DESTDIR}${file}") 30 | MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") 31 | ENDIF(EXISTS "$ENV{DESTDIR}${file}") 32 | ENDFOREACH(file) 33 | -------------------------------------------------------------------------------- /host/cmake/modules/FindLIBBLADERF.cmake: -------------------------------------------------------------------------------- 1 | # - Find BLADERF 2 | # Find the native BLADERF includes and library 3 | # This module defines 4 | # LIBBLADERF_INCLUDE_DIR, where to find rtlsdr.h, etc. 5 | # LIBBLADERF_LIBRARIES, the libraries needed to use BLADERF. 6 | # LIBBLADERF_FOUND, If false, do not try to use BLADERF. 7 | # also defined, but not for general use are 8 | # LIBBLADERF_LIBRARY, where to find the BLADERF library. 9 | 10 | #MESSAGE("LIBBLADERF_DIR set to ${LIBBLADERF_DIR}" ) 11 | 12 | FIND_PATH(LIBBLADERF_INCLUDE_DIR libbladeRF.h 13 | ${LIBBLADERF_DIR}/include 14 | /usr/local/include/libbladeRF 15 | /usr/include 16 | ) 17 | 18 | FIND_LIBRARY(LIBBLADERF_LIBRARY 19 | NAMES bladeRF 20 | PATHS ${LIBBLADERF_DIR}/libs 21 | "${LIBBLADERF_DIR}\\win32\\lib" 22 | /usr/pkgs64/lib 23 | /usr/lib64 24 | /usr/lib 25 | /usr/local/lib 26 | /usr/lib/x86_64-linux-gnu 27 | NO_DEFAULT_PATH 28 | ) 29 | 30 | IF (LIBBLADERF_LIBRARY AND LIBBLADERF_INCLUDE_DIR) 31 | SET(LIBBLADERF_LIBRARIES ${LIBBLADERF_LIBRARY}) 32 | SET(LIBBLADERF_FOUND "YES") 33 | ELSE (LIBBLADERF_LIBRARY AND LIBBLADERF_INCLUDE_DIR) 34 | SET(LIBBLADERF_FOUND "NO") 35 | ENDIF (LIBBLADERF_LIBRARY AND LIBBLADERF_INCLUDE_DIR) 36 | 37 | IF (LIBBLADERF_FOUND) 38 | IF (NOT LIBBLADERF_FIND_QUIETLY) 39 | MESSAGE(STATUS "Found BLADERF: ${LIBBLADERF_LIBRARIES}") 40 | ENDIF (NOT LIBBLADERF_FIND_QUIETLY) 41 | ELSE (LIBBLADERF_FOUND) 42 | IF (LIBBLADERF_FIND_REQUIRED) 43 | MESSAGE(FATAL_ERROR "Could not find BLADERF library") 44 | ENDIF (LIBBLADERF_FIND_REQUIRED) 45 | ENDIF (LIBBLADERF_FOUND) 46 | 47 | # Deprecated declarations. 48 | GET_FILENAME_COMPONENT (NATIVE_BLADERF_LIB_PATH ${LIBBLADERF_LIBRARY} PATH) 49 | 50 | MARK_AS_ADVANCED( 51 | LIBBLADERF_LIBRARY 52 | LIBBLADERF_INCLUDE_DIR 53 | ) 54 | 55 | -------------------------------------------------------------------------------- /host/cmake/modules/FindLIBHACKRF.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find the libhackrf library 2 | # Once done this defines 3 | # 4 | # LIBHACKRF_FOUND - system has libhackrf 5 | # LIBHACKRF_INCLUDE_DIR - the libhackrf include directory 6 | # LIBHACKRF_LIBRARIES - Link these to use libhackrf 7 | 8 | # Copyright (c) 2013 Benjamin Vernoux 9 | # 10 | 11 | 12 | if (LIBHACKRF_INCLUDE_DIR AND LIBHACKRF_LIBRARIES) 13 | 14 | # in cache already 15 | set(LIBHACKRF_FOUND TRUE) 16 | 17 | else (LIBHACKRF_INCLUDE_DIR AND LIBHACKRF_LIBRARIES) 18 | IF (NOT WIN32) 19 | # use pkg-config to get the directories and then use these values 20 | # in the FIND_PATH() and FIND_LIBRARY() calls 21 | find_package(PkgConfig) 22 | pkg_check_modules(PC_LIBHACKRF QUIET libhackrf) 23 | ENDIF(NOT WIN32) 24 | 25 | FIND_PATH(LIBHACKRF_INCLUDE_DIR 26 | NAMES hackrf.h 27 | HINTS $ENV{LIBHACKRF_DIR}/include ${PC_LIBHACKRF_INCLUDEDIR} 28 | PATH_SUFFIXES libhackrf 29 | PATHS /usr/local/include /usr/include 30 | ${CMAKE_SOURCE_DIR}/../libhackrf/src 31 | /opt/local/include 32 | ${LIBHACKRF_INCLUDE_DIR} 33 | ) 34 | 35 | set(libhackrf_library_names hackrf) 36 | 37 | FIND_LIBRARY(LIBHACKRF_LIBRARIES 38 | NAMES ${libhackrf_library_names} 39 | HINTS $ENV{LIBHACKRF_DIR}/lib ${PC_LIBHACKRF_LIBDIR} 40 | PATHS /usr/local/lib /usr/lib /opt/local/lib ${PC_LIBHACKRF_LIBDIR} ${PC_LIBHACKRF_LIBRARY_DIRS} ${CMAKE_SOURCE_DIR}/../libhackrf/src 41 | ) 42 | 43 | if(LIBHACKRF_INCLUDE_DIR) 44 | set(CMAKE_REQUIRED_INCLUDES ${LIBHACKRF_INCLUDE_DIR}) 45 | endif() 46 | 47 | if(LIBHACKRF_LIBRARIES) 48 | set(CMAKE_REQUIRED_LIBRARIES ${LIBHACKRF_LIBRARIES}) 49 | endif() 50 | 51 | include(FindPackageHandleStandardArgs) 52 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBHACKRF DEFAULT_MSG LIBHACKRF_LIBRARIES LIBHACKRF_INCLUDE_DIR) 53 | 54 | MARK_AS_ADVANCED(LIBHACKRF_INCLUDE_DIR LIBHACKRF_LIBRARIES) 55 | 56 | endif (LIBHACKRF_INCLUDE_DIR AND LIBHACKRF_LIBRARIES) -------------------------------------------------------------------------------- /host/cmake/modules/FindThreads.cmake: -------------------------------------------------------------------------------- 1 | # Updated FindThreads.cmake that supports pthread-win32 2 | # Downloaded from http://www.vtk.org/Bug/bug_view_advanced_page.php?bug_id=6399 3 | 4 | # - This module determines the thread library of the system. 5 | # 6 | # The following variables are set 7 | # CMAKE_THREAD_LIBS_INIT - the thread library 8 | # CMAKE_USE_SPROC_INIT - are we using sproc? 9 | # CMAKE_USE_WIN32_THREADS_INIT - using WIN32 threads? 10 | # CMAKE_USE_PTHREADS_INIT - are we using pthreads 11 | # CMAKE_HP_PTHREADS_INIT - are we using hp pthreads 12 | # 13 | # If use of pthreads-win32 is desired, the following variables 14 | # can be set. 15 | # 16 | # THREADS_USE_PTHREADS_WIN32 - 17 | # Setting this to true searches for the pthreads-win32 18 | # port (since CMake 2.8.0) 19 | # 20 | # THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME 21 | # C = no exceptions (default) 22 | # (NOTE: This is the default scheme on most POSIX thread 23 | # implementations and what you should probably be using) 24 | # CE = C++ Exception Handling 25 | # SE = Structure Exception Handling (MSVC only) 26 | # (NOTE: Changing this option from the default may affect 27 | # the portability of your application. See pthreads-win32 28 | # documentation for more details.) 29 | # 30 | #====================================================== 31 | # Example usage where threading library 32 | # is provided by the system: 33 | # 34 | # find_package(Threads REQUIRED) 35 | # add_executable(foo foo.cc) 36 | # target_link_libraries(foo ${CMAKE_THREAD_LIBS_INIT}) 37 | # 38 | # Example usage if pthreads-win32 is desired on Windows 39 | # or a system provided thread library: 40 | # 41 | # set(THREADS_USE_PTHREADS_WIN32 true) 42 | # find_package(Threads REQUIRED) 43 | # include_directories(${THREADS_PTHREADS_INCLUDE_DIR}) 44 | # 45 | # add_executable(foo foo.cc) 46 | # target_link_libraries(foo ${CMAKE_THREAD_LIBS_INIT}) 47 | # 48 | 49 | INCLUDE (CheckIncludeFiles) 50 | INCLUDE (CheckLibraryExists) 51 | SET(Threads_FOUND FALSE) 52 | 53 | IF(WIN32 AND NOT CYGWIN AND THREADS_USE_PTHREADS_WIN32) 54 | SET(_Threads_ptwin32 true) 55 | ENDIF() 56 | 57 | # Do we have sproc? 58 | IF(CMAKE_SYSTEM MATCHES IRIX) 59 | CHECK_INCLUDE_FILES("sys/types.h;sys/prctl.h" CMAKE_HAVE_SPROC_H) 60 | ENDIF() 61 | 62 | IF(CMAKE_HAVE_SPROC_H) 63 | # We have sproc 64 | SET(CMAKE_USE_SPROC_INIT 1) 65 | 66 | ELSEIF(_Threads_ptwin32) 67 | 68 | IF(NOT DEFINED THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME) 69 | # Assign the default scheme 70 | SET(THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME "C") 71 | ELSE() 72 | # Validate the scheme specified by the user 73 | IF(NOT THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "C" AND 74 | NOT THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "CE" AND 75 | NOT THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "SE") 76 | MESSAGE(FATAL_ERROR "See documentation for FindPthreads.cmake, only C, CE, and SE modes are allowed") 77 | ENDIF() 78 | IF(NOT MSVC AND THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "SE") 79 | MESSAGE(FATAL_ERROR "Structured Exception Handling is only allowed for MSVC") 80 | ENDIF(NOT MSVC AND THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "SE") 81 | ENDIF() 82 | 83 | FIND_PATH(THREADS_PTHREADS_INCLUDE_DIR pthread.h) 84 | 85 | # Determine the library filename 86 | IF(MSVC) 87 | SET(_Threads_pthreads_libname 88 | pthreadV${THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME}2) 89 | ELSEIF(MINGW) 90 | SET(_Threads_pthreads_libname 91 | pthreadG${THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME}2) 92 | ELSE() 93 | MESSAGE(FATAL_ERROR "This should never happen") 94 | ENDIF() 95 | 96 | # Use the include path to help find the library if possible 97 | SET(_Threads_lib_paths "") 98 | IF(THREADS_PTHREADS_INCLUDE_DIR) 99 | GET_FILENAME_COMPONENT(_Threads_root_dir 100 | ${THREADS_PTHREADS_INCLUDE_DIR} PATH) 101 | SET(_Threads_lib_paths ${_Threads_root_dir}/lib) 102 | ENDIF() 103 | FIND_LIBRARY(THREADS_PTHREADS_WIN32_LIBRARY 104 | NAMES ${_Threads_pthreads_libname} 105 | PATHS ${_Threads_lib_paths} 106 | DOC "The Portable Threads Library for Win32" 107 | NO_SYSTEM_PATH 108 | ) 109 | 110 | IF(THREADS_PTHREADS_INCLUDE_DIR AND THREADS_PTHREADS_WIN32_LIBRARY) 111 | MARK_AS_ADVANCED(THREADS_PTHREADS_INCLUDE_DIR) 112 | SET(CMAKE_THREAD_LIBS_INIT ${THREADS_PTHREADS_WIN32_LIBRARY}) 113 | SET(CMAKE_HAVE_THREADS_LIBRARY 1) 114 | SET(Threads_FOUND TRUE) 115 | ENDIF() 116 | 117 | MARK_AS_ADVANCED(THREADS_PTHREADS_WIN32_LIBRARY) 118 | 119 | ELSE() 120 | # Do we have pthreads? 121 | CHECK_INCLUDE_FILES("pthread.h" CMAKE_HAVE_PTHREAD_H) 122 | IF(CMAKE_HAVE_PTHREAD_H) 123 | 124 | # 125 | # We have pthread.h 126 | # Let's check for the library now. 127 | # 128 | SET(CMAKE_HAVE_THREADS_LIBRARY) 129 | IF(NOT THREADS_HAVE_PTHREAD_ARG) 130 | 131 | # Do we have -lpthreads 132 | CHECK_LIBRARY_EXISTS(pthreads pthread_create "" CMAKE_HAVE_PTHREADS_CREATE) 133 | IF(CMAKE_HAVE_PTHREADS_CREATE) 134 | SET(CMAKE_THREAD_LIBS_INIT "-lpthreads") 135 | SET(CMAKE_HAVE_THREADS_LIBRARY 1) 136 | SET(Threads_FOUND TRUE) 137 | ENDIF() 138 | 139 | # Ok, how about -lpthread 140 | CHECK_LIBRARY_EXISTS(pthread pthread_create "" CMAKE_HAVE_PTHREAD_CREATE) 141 | IF(CMAKE_HAVE_PTHREAD_CREATE) 142 | SET(CMAKE_THREAD_LIBS_INIT "-lpthread") 143 | SET(Threads_FOUND TRUE) 144 | SET(CMAKE_HAVE_THREADS_LIBRARY 1) 145 | ENDIF() 146 | 147 | IF(CMAKE_SYSTEM MATCHES "SunOS.*") 148 | # On sun also check for -lthread 149 | CHECK_LIBRARY_EXISTS(thread thr_create "" CMAKE_HAVE_THR_CREATE) 150 | IF(CMAKE_HAVE_THR_CREATE) 151 | SET(CMAKE_THREAD_LIBS_INIT "-lthread") 152 | SET(CMAKE_HAVE_THREADS_LIBRARY 1) 153 | SET(Threads_FOUND TRUE) 154 | ENDIF() 155 | ENDIF(CMAKE_SYSTEM MATCHES "SunOS.*") 156 | 157 | ENDIF(NOT THREADS_HAVE_PTHREAD_ARG) 158 | 159 | IF(NOT CMAKE_HAVE_THREADS_LIBRARY) 160 | # If we did not found -lpthread, -lpthread, or -lthread, look for -pthread 161 | IF("THREADS_HAVE_PTHREAD_ARG" MATCHES "^THREADS_HAVE_PTHREAD_ARG") 162 | MESSAGE(STATUS "Check if compiler accepts -pthread") 163 | TRY_RUN(THREADS_PTHREAD_ARG THREADS_HAVE_PTHREAD_ARG 164 | ${CMAKE_BINARY_DIR} 165 | ${CMAKE_ROOT}/Modules/CheckForPthreads.c 166 | CMAKE_FLAGS -DLINK_LIBRARIES:STRING=-pthread 167 | COMPILE_OUTPUT_VARIABLE OUTPUT) 168 | 169 | IF(THREADS_HAVE_PTHREAD_ARG) 170 | IF(THREADS_PTHREAD_ARG MATCHES "^2$") 171 | SET(Threads_FOUND TRUE) 172 | MESSAGE(STATUS "Check if compiler accepts -pthread - yes") 173 | ELSE() 174 | MESSAGE(STATUS "Check if compiler accepts -pthread - no") 175 | FILE(APPEND 176 | ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log 177 | "Determining if compiler accepts -pthread returned ${THREADS_PTHREAD_ARG} instead of 2. The compiler had the following output:\n${OUTPUT}\n\n") 178 | ENDIF() 179 | ELSE() 180 | MESSAGE(STATUS "Check if compiler accepts -pthread - no") 181 | FILE(APPEND 182 | ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log 183 | "Determining if compiler accepts -pthread failed with the following output:\n${OUTPUT}\n\n") 184 | ENDIF() 185 | 186 | ENDIF("THREADS_HAVE_PTHREAD_ARG" MATCHES "^THREADS_HAVE_PTHREAD_ARG") 187 | 188 | IF(THREADS_HAVE_PTHREAD_ARG) 189 | SET(Threads_FOUND TRUE) 190 | SET(CMAKE_THREAD_LIBS_INIT "-pthread") 191 | ENDIF() 192 | 193 | ENDIF(NOT CMAKE_HAVE_THREADS_LIBRARY) 194 | ENDIF(CMAKE_HAVE_PTHREAD_H) 195 | ENDIF() 196 | 197 | IF(CMAKE_THREAD_LIBS_INIT) 198 | SET(CMAKE_USE_PTHREADS_INIT 1) 199 | SET(Threads_FOUND TRUE) 200 | ENDIF() 201 | 202 | IF(CMAKE_SYSTEM MATCHES "Windows" 203 | AND NOT THREADS_USE_PTHREADS_WIN32) 204 | SET(CMAKE_USE_WIN32_THREADS_INIT 1) 205 | SET(Threads_FOUND TRUE) 206 | ENDIF() 207 | 208 | IF(CMAKE_USE_PTHREADS_INIT) 209 | IF(CMAKE_SYSTEM MATCHES "HP-UX-*") 210 | # Use libcma if it exists and can be used. It provides more 211 | # symbols than the plain pthread library. CMA threads 212 | # have actually been deprecated: 213 | # http://docs.hp.com/en/B3920-90091/ch12s03.html#d0e11395 214 | # http://docs.hp.com/en/947/d8.html 215 | # but we need to maintain compatibility here. 216 | # The CMAKE_HP_PTHREADS setting actually indicates whether CMA threads 217 | # are available. 218 | CHECK_LIBRARY_EXISTS(cma pthread_attr_create "" CMAKE_HAVE_HP_CMA) 219 | IF(CMAKE_HAVE_HP_CMA) 220 | SET(CMAKE_THREAD_LIBS_INIT "-lcma") 221 | SET(CMAKE_HP_PTHREADS_INIT 1) 222 | SET(Threads_FOUND TRUE) 223 | ENDIF(CMAKE_HAVE_HP_CMA) 224 | SET(CMAKE_USE_PTHREADS_INIT 1) 225 | ENDIF() 226 | 227 | IF(CMAKE_SYSTEM MATCHES "OSF1-V*") 228 | SET(CMAKE_USE_PTHREADS_INIT 0) 229 | SET(CMAKE_THREAD_LIBS_INIT ) 230 | ENDIF() 231 | 232 | IF(CMAKE_SYSTEM MATCHES "CYGWIN_NT*") 233 | SET(CMAKE_USE_PTHREADS_INIT 1) 234 | SET(Threads_FOUND TRUE) 235 | SET(CMAKE_THREAD_LIBS_INIT ) 236 | SET(CMAKE_USE_WIN32_THREADS_INIT 0) 237 | ENDIF() 238 | ENDIF(CMAKE_USE_PTHREADS_INIT) 239 | 240 | INCLUDE(FindPackageHandleStandardArgs) 241 | IF(_Threads_ptwin32) 242 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(Threads DEFAULT_MSG 243 | THREADS_PTHREADS_WIN32_LIBRARY THREADS_PTHREADS_INCLUDE_DIR) 244 | ELSE() 245 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(Threads DEFAULT_MSG Threads_FOUND) 246 | ENDIF() 247 | -------------------------------------------------------------------------------- /host/cmake/modules/FindUSB1.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find the freetype library 2 | # Once done this defines 3 | # 4 | # LIBUSB_FOUND - system has libusb 5 | # LIBUSB_INCLUDE_DIR - the libusb include directory 6 | # LIBUSB_LIBRARIES - Link these to use libusb 7 | 8 | # Copyright (c) 2006, 2008 Laurent Montel, 9 | # 10 | # Redistribution and use is allowed according to the terms of the BSD license. 11 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file. 12 | 13 | 14 | if (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES) 15 | 16 | # in cache already 17 | set(LIBUSB_FOUND TRUE) 18 | 19 | else (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES) 20 | IF (NOT WIN32) 21 | # use pkg-config to get the directories and then use these values 22 | # in the FIND_PATH() and FIND_LIBRARY() calls 23 | find_package(PkgConfig) 24 | pkg_check_modules(PC_LIBUSB libusb-1.0) 25 | ENDIF(NOT WIN32) 26 | 27 | FIND_PATH(LIBUSB_INCLUDE_DIR libusb.h 28 | PATHS ${PC_LIBUSB_INCLUDEDIR} ${PC_LIBUSB_INCLUDE_DIRS}) 29 | 30 | FIND_LIBRARY(LIBUSB_LIBRARIES NAMES usb-1.0 31 | PATHS ${PC_LIBUSB_LIBDIR} ${PC_LIBUSB_LIBRARY_DIRS}) 32 | 33 | include(FindPackageHandleStandardArgs) 34 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBUSB DEFAULT_MSG LIBUSB_LIBRARIES LIBUSB_INCLUDE_DIR) 35 | 36 | MARK_AS_ADVANCED(LIBUSB_INCLUDE_DIR LIBUSB_LIBRARIES) 37 | 38 | endif (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES) -------------------------------------------------------------------------------- /matlab/get_number.m: -------------------------------------------------------------------------------- 1 | function a = get_number 2 | a = [0 1 0 1 0 1 0 1 0 1 1 0 1 0 1 1 0 1 1 1 1 1 0 1 ... 3 | 1 0 0 1 0 0 0 1 0 1 1 1 0 0 0 1 1 1 1 1 0 0 1 1 ... 4 | 1 1 1 0 1 1 1 1 1 0 0 0 1 0 1 0 0 0 1 0 0 1 0 1 ... 5 | 1 0 0 1 1 1 0 0 0 0 1 0 0 1 0 1 0 0 1 0 0 1 1 0 ... 6 | 1 0 0 0 1 1 0 1 1 1 0 1 0 1 1 0 0 0 0 1 1 1 0 0 ... 7 | 0 1 0 0 1 0 1 0 1 0 0 1 0 0 0 0 1 1 1 0 0 1 0 1 ... 8 | 0 0 1 0 0 0 1 0 0 0 0 1 0 0 1 1 1 1 0 1 1 0 1 1 ... 9 | 0 1 1 0 0 1 1 0 0 0 0 1 1 0 1 1 0 1 0 1 1 0 0 1 ... 10 | 1 0 0 1 0 1 1 1 1 1 0 1 0 1 0 1 1 1 0 0 0 1 1 0 ... 11 | 1 1 0 0 1 0 0 0 0 1 0 1 0 1 1 1 0 0 0 1 0 0 0 1 ... 12 | 0 1 1 0 1 1 0 1 0 1 1 1 1 1 0 0 0 1 1 0 1 0 0 0 ... 13 | 1 0 1 1 1 1 1 1 1 1 0 1 1 0 0 0 1 0 1 1 0 0 1 1 ... 14 | 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 1 0 1 1 0 1 1 ... 15 | 1 0 1 1 0 1 1 0 0 1 0 1 1 0 1 0 0 0 1 1 1 1 1 1 ... 16 | 1 0 0 1 0 0 0 1 1 1 0 1 0 1 0 0 1 0 1 1 1 0 1 1 ... 17 | 1 1 0 0 1 0 1 1 1 1 0 0 0 1 1 0 ]; 18 | -------------------------------------------------------------------------------- /matlab/get_signal_from_hackrf_bin.m: -------------------------------------------------------------------------------- 1 | function [s, status] = get_signal_from_hackrf_bin(filename, num_sample_read) 2 | s = int8(-1); 3 | status = false; 4 | 5 | fid = fopen(filename); 6 | 7 | if fid == -1 8 | disp('get_signal_from_hackrf_bin: Can not open file!'); 9 | status = true; 10 | return; 11 | end 12 | 13 | [s, count] = fread(fid, num_sample_read*2, 'int8'); 14 | fclose(fid); 15 | 16 | % s = int8(s); 17 | 18 | if num_sample_read~=inf && count ~= (num_sample_read*2) 19 | disp('get_signal_from_hackrf_bin: No enough samples in the file!'); 20 | status = true; 21 | return; 22 | end 23 | 24 | % s = single( (s(1:2:end) + 1i.*s(2:2:end))./128 ); 25 | % s = (s(1:2:end) + 1i.*s(2:2:end))./128; 26 | 27 | s = complex(s(1:2:end), s(2:2:end)); 28 | 29 | % len_s = length(s); 30 | % 31 | % s = s((len_s/2)+1:end); 32 | -------------------------------------------------------------------------------- /matlab/save_int_var_for_c.m: -------------------------------------------------------------------------------- 1 | function save_int_var_for_c(a, type_and_name, filename, access_mode) 2 | fid = fopen(filename, access_mode); 3 | if fid == -1 4 | disp(['save_var_for_c: fopen' filename ' failed!']); 5 | return; 6 | end 7 | 8 | fprintf(fid, [type_and_name, '[%d] = {'], length(a) ); 9 | for i = 1 : length(a) 10 | if mod(i-1, 24) == 0 11 | fprintf(fid, '\n'); 12 | end 13 | fprintf(fid, '%d, ', a(i)); 14 | end 15 | fprintf(fid, '};\n\n'); 16 | 17 | fclose(fid); 18 | -------------------------------------------------------------------------------- /matlab/save_int_var_for_c_2d.m: -------------------------------------------------------------------------------- 1 | function save_int_var_for_c_2d(a, type_and_name, filename, access_mode) 2 | fid = fopen(filename, access_mode); 3 | if fid == -1 4 | disp(['save_int_var_for_c_2d: fopen' filename ' failed!']); 5 | return; 6 | end 7 | 8 | [num_row, num_col] = size(a); 9 | 10 | fprintf(fid, [type_and_name, '[%d][%d] = {'], num_row, num_col ); 11 | for j = 1 : num_row 12 | fprintf(fid, '\n{'); 13 | for i = 1 : num_col 14 | fprintf(fid, '%d, ', a(j,i)); 15 | end 16 | fprintf(fid, '},'); 17 | end 18 | 19 | fprintf(fid, '\n};\n\n'); 20 | 21 | fclose(fid); 22 | -------------------------------------------------------------------------------- /matlab/scramble_gen.m: -------------------------------------------------------------------------------- 1 | function a = scramble_gen(channel_number, num_bit, filename, varargin) 2 | 3 | bit_store = zeros(1, 7); 4 | bit_store_update = zeros(1, 7); 5 | 6 | channel_number_bin = dec2bin(channel_number, 6); 7 | 8 | bit_store(1) = 1; 9 | bit_store(2) = ( channel_number_bin(1) == '1' ); 10 | bit_store(3) = ( channel_number_bin(2) == '1' ); 11 | bit_store(4) = ( channel_number_bin(3) == '1' ); 12 | bit_store(5) = ( channel_number_bin(4) == '1' ); 13 | bit_store(6) = ( channel_number_bin(5) == '1' ); 14 | bit_store(7) = ( channel_number_bin(6) == '1' ); 15 | 16 | bit_seq = zeros(1, num_bit); 17 | for i = 1 : num_bit 18 | bit_seq(i) = bit_store(7); 19 | 20 | bit_store_update(1) = bit_store(7); 21 | 22 | bit_store_update(2) = bit_store(1); 23 | bit_store_update(3) = bit_store(2); 24 | bit_store_update(4) = bit_store(3); 25 | 26 | bit_store_update(5) = mod(bit_store(4)+bit_store(7), 2); 27 | 28 | bit_store_update(6) = bit_store(5); 29 | bit_store_update(7) = bit_store(6); 30 | 31 | bit_store = bit_store_update; 32 | end 33 | 34 | a = zeros(1, num_bit/8); 35 | 36 | for i = 0 : 8 : num_bit-1 37 | idx = floor(i/8) + 1; 38 | a(idx) = bit_seq(i+1) + bit_seq(i+2)*2 + bit_seq(i+3)*4 + bit_seq(i+4)*8 + bit_seq(i+5)*16 + bit_seq(i+6)*32 + bit_seq(i+7)*64 + bit_seq(i+8)*128; 39 | end 40 | 41 | if nargin == 3 42 | save_int_var_for_c(a, ['const uint8_t const scramble_table_ch' num2str(channel_number)], filename, 'w'); 43 | end 44 | 45 | -------------------------------------------------------------------------------- /matlab/test_fixed_point.m: -------------------------------------------------------------------------------- 1 | clear all; 2 | close all; 3 | 4 | % original float point version 5 | gauss_coef = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.231548e-14, 2.007605e-11, 7.561773e-09, 1.197935e-06, 8.050684e-05, 2.326833e-03, 2.959908e-02, 1.727474e-01, 4.999195e-01, 8.249246e-01, 9.408018e-01, 8.249246e-01, 4.999195e-01, 1.727474e-01, 2.959908e-02, 2.326833e-03, 8.050684e-05, 1.197935e-06, 7.561773e-09, 2.007605e-11, 2.231548e-14, 0]; 6 | %plot(gauss_coef, 'r+-'); axis([0 length(gauss_coef) 0 0.0001]); 7 | 8 | % short it to 16 points: 9 | gauss_coef = [7.561773e-09, 1.197935e-06, 8.050684e-05, 2.326833e-03, 2.959908e-02, 1.727474e-01, 4.999195e-01, 8.249246e-01, 9.408018e-01, 8.249246e-01, 4.999195e-01, 1.727474e-01, 2.959908e-02, 2.326833e-03, 8.050684e-05, 1.197935e-06]; 10 | %plot(gauss_coef, 'r+-'); 11 | 12 | SAMPLE_PER_SYMBOL = 4; 13 | LEN_GAUSS_FILTER = length(gauss_coef)/SAMPLE_PER_SYMBOL; 14 | MAX_NUM_PHY_BYTE = 47; 15 | MAX_NUM_PHY_SAMPLE = ((MAX_NUM_PHY_BYTE*8*SAMPLE_PER_SYMBOL)+(LEN_GAUSS_FILTER*SAMPLE_PER_SYMBOL)); 16 | MOD_IDX = 0.5; 17 | AMPLITUDE = 127; 18 | tmp_phy_bit_over_sampling = zeros(1, MAX_NUM_PHY_SAMPLE + 2*LEN_GAUSS_FILTER*SAMPLE_PER_SYMBOL); 19 | tmp_phy_bit_over_sampling = zeros(1, MAX_NUM_PHY_SAMPLE); 20 | 21 | num_bit = MAX_NUM_PHY_BYTE*8; 22 | %bit = round(rand(1, num_bit)); 23 | bit = get_number; 24 | num_bit_oversample = num_bit*SAMPLE_PER_SYMBOL; 25 | len_gauss_oversample = LEN_GAUSS_FILTER*SAMPLE_PER_SYMBOL; 26 | num_sample = num_bit_oversample + len_gauss_oversample; 27 | 28 | pre_len = len_gauss_oversample-1; 29 | tmp_phy_bit_over_sampling(1:pre_len) = 0.0; 30 | 31 | post_sp = num_bit_oversample + pre_len + 1; 32 | post_ep = post_sp + pre_len - 1; 33 | tmp_phy_bit_over_sampling(post_sp:post_ep) = 0.0; 34 | 35 | tmp_phy_bit_over_sampling((pre_len+1):(pre_len+num_bit_oversample)) = 0; 36 | tmp_phy_bit_over_sampling((pre_len+1):SAMPLE_PER_SYMBOL:(pre_len+num_bit_oversample)) = bit.*2 - 1; 37 | 38 | % len_conv_result = length(tmp_phy_bit_over_sampling) - len_gauss_oversample + 1 39 | % = post_ep - len_gauss_oversample + 1 40 | % = num_bit_oversample + pre_len + 1 + pre_len - 1 - len_gauss_oversample + 1 41 | % = num_bit_oversample + 2*(len_gauss_oversample-1) - len_gauss_oversample + 1 42 | % = num_bit_oversample + len_gauss_oversample - 1 43 | len_conv_result = num_sample - 1; 44 | 45 | % -------------------------------------- float point reference ----------------------------------------------- 46 | for i = 1 : len_conv_result 47 | acc = 0; 48 | for j = 1 : len_gauss_oversample 49 | acc = acc + gauss_coef(len_gauss_oversample-j+1)*tmp_phy_bit_over_sampling(i+j-1); %num_sample - 1+len_gauss_oversample-1= length(tmp_phy_bit_over_sampling) 50 | end 51 | tmp_phy_bit_over_sampling1(i) = acc; 52 | end 53 | 54 | tmp = 0; 55 | sample = zeros(1, 2*num_sample); 56 | sample(1) = round( cos(tmp)*AMPLITUDE ); 57 | sample(2) = round( sin(tmp)*AMPLITUDE ); 58 | for i=2:num_sample 59 | tmp = tmp + (pi*MOD_IDX)*tmp_phy_bit_over_sampling1(i-1)/(SAMPLE_PER_SYMBOL); 60 | sample((i-1)*2 + 1) = round( cos(tmp)*AMPLITUDE ); 61 | sample((i-1)*2 + 2) = round( sin(tmp)*AMPLITUDE ); 62 | end 63 | 64 | % -------------------------------------------------- fixed point ------------- ----------------------------------------------- 65 | tmp_phy_bit_over_sampling_int16 = int16(tmp_phy_bit_over_sampling); 66 | tmp_phy_bit_over_sampling1_int16 = int16(tmp_phy_bit_over_sampling1); 67 | gauss_coef_scale = 128; 68 | cos_table_size = 1024; % 0 to 2PI 69 | gauss_coef_int16 = int16(gauss_coef.*gauss_coef_scale); 70 | 71 | cos_table_int8 = int8(zeros(1, cos_table_size)); 72 | sin_table_int8 = int8(zeros(1, cos_table_size)); 73 | for i=1:cos_table_size 74 | cos_table_int8(i) = int8(cos(2*pi*(i-1)/cos_table_size)*127); 75 | sin_table_int8(i) = int8(sin(2*pi*(i-1)/cos_table_size)*127); 76 | end 77 | 78 | save_int_var_for_c(gauss_coef_int16./2, 'const int8_t const gauss_coef_int8', 'gauss_cos_sin_table.h', 'w'); 79 | save_int_var_for_c(cos_table_int8, 'const int8_t const cos_table_int8', 'gauss_cos_sin_table.h', 'a'); 80 | save_int_var_for_c(sin_table_int8, 'const int8_t const sin_table_int8', 'gauss_cos_sin_table.h', 'a'); 81 | 82 | for i = 1 : len_conv_result 83 | acc_int16 = int16(0); 84 | for j = 1 : len_gauss_oversample 85 | acc_int16 = acc_int16 + gauss_coef_int16(len_gauss_oversample-j+1)*tmp_phy_bit_over_sampling_int16(i+j-1); 86 | end 87 | tmp_phy_bit_over_sampling1_int16(i) = acc_int16; 88 | end 89 | 90 | %figure; 91 | %subplot(2,1,1); plot(tmp_phy_bit_over_sampling1_int16); hold on; 92 | %plot(tmp_phy_bit_over_sampling1.*128, 'r.'); 93 | %subplot(2,1,2); plot(abs(double(tmp_phy_bit_over_sampling1_int16)-tmp_phy_bit_over_sampling1.*128)); 94 | 95 | phase_per_step = 2*pi/cos_table_size; 96 | phase_delta_orig = ((pi*MOD_IDX)/SAMPLE_PER_SYMBOL)/gauss_coef_scale; 97 | enlarge_scale = phase_per_step/phase_delta_orig 98 | if enlarge_scale <1 99 | tmp_phy_bit_over_sampling1_int16 = tmp_phy_bit_over_sampling1_int16.*int16(1/enlarge_scale); 100 | else 101 | tmp_phy_bit_over_sampling1_int16 = tmp_phy_bit_over_sampling1_int16./int16(enlarge_scale); 102 | end 103 | 104 | tmp_int16 = int16(0); 105 | sample_int16 = int8(zeros(1, 2*num_sample)); 106 | sample_int16(1) = cos_table_int8(tmp_int16+1); 107 | sample_int16(2) = sin_table_int8(tmp_int16+1); 108 | for i=2:num_sample 109 | tmp_int16 = tmp_int16 + tmp_phy_bit_over_sampling1_int16(i-1); 110 | tmp_int16 = mod(tmp_int16, int16(cos_table_size)); 111 | sample_int16((i-1)*2 + 1) = cos_table_int8(tmp_int16+1); 112 | sample_int16((i-1)*2 + 2) = sin_table_int8(tmp_int16+1); 113 | end 114 | 115 | figure(1); 116 | subplot(2,1,1); plot(sample_int16); 117 | ref_sample = get_number1; 118 | %ref_sample = sample; 119 | hold on; plot(ref_sample, 'r.'); 120 | subplot(2,1,2); plot((double(sample_int16)-ref_sample)); -------------------------------------------------------------------------------- /matlab/test_float_point.m: -------------------------------------------------------------------------------- 1 | clear all; 2 | close all; 3 | 4 | % original float point version 5 | gauss_coef = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.231548e-14, 2.007605e-11, 7.561773e-09, 1.197935e-06, 8.050684e-05, 2.326833e-03, 2.959908e-02, 1.727474e-01, 4.999195e-01, 8.249246e-01, 9.408018e-01, 8.249246e-01, 4.999195e-01, 1.727474e-01, 2.959908e-02, 2.326833e-03, 8.050684e-05, 1.197935e-06, 7.561773e-09, 2.007605e-11, 2.231548e-14, 0]; 6 | %plot(gauss_coef, 'r+-'); axis([0 length(gauss_coef) 0 0.0001]); 7 | 8 | % short it to 16 points: 9 | gauss_coef = [7.561773e-09, 1.197935e-06, 8.050684e-05, 2.326833e-03, 2.959908e-02, 1.727474e-01, 4.999195e-01, 8.249246e-01, 9.408018e-01, 8.249246e-01, 4.999195e-01, 1.727474e-01, 2.959908e-02, 2.326833e-03, 8.050684e-05, 1.197935e-06]; 10 | %plot(gauss_coef, 'r+-'); 11 | 12 | SAMPLE_PER_SYMBOL = 4; 13 | LEN_GAUSS_FILTER = length(gauss_coef)/SAMPLE_PER_SYMBOL; 14 | MAX_NUM_PHY_BYTE = 47; 15 | MAX_NUM_PHY_SAMPLE = ((MAX_NUM_PHY_BYTE*8*SAMPLE_PER_SYMBOL)+(LEN_GAUSS_FILTER*SAMPLE_PER_SYMBOL)); 16 | MOD_IDX = 0.5; 17 | AMPLITUDE = 127; 18 | tmp_phy_bit_over_sampling = zeros(1, MAX_NUM_PHY_SAMPLE + 2*LEN_GAUSS_FILTER*SAMPLE_PER_SYMBOL); 19 | tmp_phy_bit_over_sampling = zeros(1, MAX_NUM_PHY_SAMPLE); 20 | 21 | num_bit = MAX_NUM_PHY_BYTE*8; 22 | %bit = round(rand(1, num_bit)); 23 | bit = get_number; 24 | num_bit_oversample = num_bit*SAMPLE_PER_SYMBOL; 25 | len_gauss_oversample = LEN_GAUSS_FILTER*SAMPLE_PER_SYMBOL; 26 | num_sample = num_bit_oversample + len_gauss_oversample; 27 | 28 | pre_len = len_gauss_oversample-1; 29 | tmp_phy_bit_over_sampling(1:pre_len) = 0.0; 30 | 31 | post_sp = num_bit_oversample + pre_len + 1; 32 | post_ep = post_sp + pre_len - 1; 33 | tmp_phy_bit_over_sampling(post_sp:post_ep) = 0.0; 34 | 35 | tmp_phy_bit_over_sampling((pre_len+1):(pre_len+num_bit_oversample)) = 0; 36 | tmp_phy_bit_over_sampling((pre_len+1):SAMPLE_PER_SYMBOL:(pre_len+num_bit_oversample)) = bit.*2 - 1; 37 | 38 | % len_conv_result = length(tmp_phy_bit_over_sampling) - len_gauss_oversample + 1 39 | % = post_ep - len_gauss_oversample + 1 40 | % = num_bit_oversample + pre_len + 1 + pre_len - 1 - len_gauss_oversample + 1 41 | % = num_bit_oversample + 2*(len_gauss_oversample-1) - len_gauss_oversample + 1 42 | % = num_bit_oversample + len_gauss_oversample - 1 43 | len_conv_result = num_sample - 1; 44 | 45 | % -------------------------------------- float point reference ----------------------------------------------- 46 | for i = 1 : len_conv_result 47 | acc = 0; 48 | for j = 1 : len_gauss_oversample 49 | acc = acc + gauss_coef(len_gauss_oversample-j+1)*tmp_phy_bit_over_sampling(i+j-1); %num_sample - 1+len_gauss_oversample-1= length(tmp_phy_bit_over_sampling) 50 | end 51 | tmp_phy_bit_over_sampling1(i) = acc; 52 | end 53 | 54 | tmp = 0; 55 | sample = zeros(1, 2*num_sample); 56 | sample(1) = round( cos(tmp)*AMPLITUDE ); 57 | sample(2) = round( sin(tmp)*AMPLITUDE ); 58 | for i=2:num_sample 59 | tmp = tmp + (pi*MOD_IDX)*tmp_phy_bit_over_sampling1(i-1)/(SAMPLE_PER_SYMBOL); 60 | sample((i-1)*2 + 1) = round( cos(tmp)*AMPLITUDE ); 61 | sample((i-1)*2 + 2) = round( sin(tmp)*AMPLITUDE ); 62 | end 63 | 64 | figure(1); 65 | subplot(2,1,1); plot(sample); 66 | ref_sample = get_number1; 67 | hold on; plot(ref_sample, 'r.'); 68 | subplot(2,1,2); plot(abs(sample-ref_sample)); 69 | -------------------------------------------------------------------------------- /matlab/test_scramble_gen_all_channel.m: -------------------------------------------------------------------------------- 1 | clear all; 2 | close all; 3 | 4 | num_bit = 42*8; % 42 = 2(pdu header) + 37(maximum payload length) + 3(CRC octets) 5 | a = zeros(40, num_bit/8); 6 | for channel_number = 0:39 7 | a(channel_number+1, :) = scramble_gen(channel_number, num_bit, ' ', 1); 8 | end 9 | 10 | save_int_var_for_c_2d(a, 'const uint8_t const scramble_table', 'scramble_table.h', 'w'); 11 | -------------------------------------------------------------------------------- /open_btle_baseband_chip/README.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # The open-source BTLE (Bluetooth Low Energy) baseband chip design 8 | 9 | This is an open-source Bluetooth Low Energy controller (baseband part) project written in Verilog: https://github.com/JiaoXianjun/BTLE/tree/master/verilog 10 | 11 | There is also a Python bit-true algorithm model for the Verilog project: https://github.com/JiaoXianjun/BTLE/tree/master/python 12 | 13 | Please refer to [open_btle_baseband_chip.md](open_btle_baseband_chip.md) for detailed algorithm explanation and local setup/running. 14 | 15 | You can also upload and run [open_btle_baseband_chip.ipynb](open_btle_baseband_chip.ipynb) in Google Colab to: read and run Python/Verilog simulation, synthesis, mapping, routing, etc., with OpenLane2 workflow targeting SkyWater 130 PDK and Xilinx Vivado targeting FPGA. 16 | 17 | Here are some quick pieces to get you some basic ideas about the project. 18 | 19 | - [[The main features and innovative points](#The-main-features-and-innovative-points)] 20 | - [[The main references contributing to this project](#The-main-references-contributing-to-this-project)] 21 | - [[The main contents of the Python notebook](#The-main-contents-of-the-Python-notebook)] 22 | - [[The top architecture and the BTLE chip refers to the LE controller](#The-top-architecture-and-the-BTLE-chip-refers-to-the-LE-controller)] 23 | - [[The LE controller principle and the scope of this project](#The-LE-controller-principle-and-the-scope-of-this-project)] 24 | - [[The example of the waveform during the Python and Verilog simulation](#The-example-of-the-waveform-during-the-Python-and-Verilog-simulation)] 25 | - [[The result of the Xilinx Zynq 7z020 FPGA target](#The-result-of-the-Xilinx-Zynq-7z020-FPGA-target)] 26 | - [[The GDSII of the btle rx core](#The-GDSII-of-the-btle-rx-core)] 27 | - [[The Detailed Placement and CTS of the whole project](#The-Detailed-Placement-and-CTS-of-the-whole-project)] 28 | 29 | ## The main features and innovative points 30 | - Sub set of [BTLE core spec v5.3](https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=521059) 31 | - LE 1M, with uncoded data at 1 Mb/s 32 | - GFSK (Gaussian Frequency Shift Keying) with BT(Bandwidth-bit period product)=0.5 33 | - Modulation index 0.5 34 | - Preamble has 1 octet 35 | - Access address has 4 octets 36 | - PDU (Protocol Data Unit) has 2-39 octets 37 | - CRC (Cyclic Redundancy Check) has 3 octets 38 | - BER (Bit Error Rate) performance 39 | - With max 50PPM clock error, BER 0.1% @ 24.5dB SNR 40 | - With 20PPM clock error, BER 0.1% @ 11.5dB SNR 41 | - Configurable gauss filter taps -- Flexible bandwidth/spectrum-shape 42 | - Support non-standard BT value or other phase smoothing strategy, such as GMSK (Gaussian Minimum Shift Keying). 43 | - Configurable COS and SIN table -- Flexible modulation index 44 | - Support non-standard frequency deviation 45 | - 16MHz main clock speed. 8x oversampling in both transmitter and receiver 46 | - oversampling rate is customizable in design time 47 | 48 | ## The main references contributing to this project 49 | 50 | Link|Role 51 | ----|---- 52 | https://www.bluetooth.com/specifications/specs/core-specification-5-3/|Core Specification 5.3 is the main reference. Mainly PartA&B of Vol6: Low Energy Controller 53 | https://github.com/JiaoXianjun/BTLE|The starting point of this project. Created ~10 years ago by me. The new design files are in BTLE/python and BTLE/verilog directories 54 | https://colab.research.google.com/github/efabless/openlane2/blob/main/notebook.ipynb|The OpenLane2 work flow I learnt/copied 55 | https://github.com/halftop/Interface-Protocol-in-Verilog|general_uart is used for HCI (Host Controller Interface) 56 | https://github.com/KennethWilke/sv-dpram|Dual port ram (modified in this project) IP 57 | https://public.ccsds.org/Pubs/413x0g3e1.pdf|Figure 3-3: GMSK Using a Quadrature Modulator -- The GFSK modulation method adopted in this project 58 | https://research.utwente.nl/en/publications/bluetooth-demodulation-algorithms-and-their-performance|Fig. 6. Phase-shift discriminator -- The GFSK demodulation method adopted in this project 59 | 60 | 61 | ## The main contents of the Python notebook 62 | - **BTLE chip architecture** 63 | - **The overall design and implementation methodology** 64 | - **Prior arts analysis** 65 | - **Introduction of the reference SDR BTLE project and its users** 66 | - **Basic principle of BTLE algorithm and structure of the project files** 67 | - **Align the Python algorithms to the SDR BTLE project** 68 | - **Use Python script to evaluate BER under different clock error** 69 | - **Use Python script and Verilog testbench to simulate the design** 70 | - **Synthesis and Implementation for Xilinx FPGA** 71 | - **Run through OpenLane2 SKY130 PDK flow to generate GDSII** 72 | 73 | ## The top architecture and the BTLE chip refers to the LE controller 74 | 75 | ![](architecture.png) 76 | 77 | ## The LE controller principle and the scope of this project 78 | 79 | ![](btle-principle.png) 80 | 81 | ## The example of the waveform during the Python and Verilog simulation 82 | 83 | ![](btle-python-verilog-waveform.png) 84 | 85 | ## The result of the Xilinx Zynq 7z020 FPGA target 86 | 87 | ![](btle_controller_xilinx_7z020.jpg) 88 | 89 | ## The GDSII of the btle rx core 90 | 91 | Note: Static Timing Analysis (Post-PnR) failed 92 | 93 | ![](btle_rx_core-openlane-GDSII.png) 94 | 95 | ## The Detailed Placement and CTS of the whole project 96 | 97 | Note: Global Routing failed 98 | 99 | ![](btle-top-openlane-detailed-placement-cts.png) 100 | -------------------------------------------------------------------------------- /open_btle_baseband_chip/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaoXianjun/BTLE/d431f70e4741b8f0e83c8d0ee50d14a5e5e6e63e/open_btle_baseband_chip/architecture.png -------------------------------------------------------------------------------- /open_btle_baseband_chip/btle-principle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaoXianjun/BTLE/d431f70e4741b8f0e83c8d0ee50d14a5e5e6e63e/open_btle_baseband_chip/btle-principle.png -------------------------------------------------------------------------------- /open_btle_baseband_chip/btle-python-verilog-waveform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaoXianjun/BTLE/d431f70e4741b8f0e83c8d0ee50d14a5e5e6e63e/open_btle_baseband_chip/btle-python-verilog-waveform.png -------------------------------------------------------------------------------- /open_btle_baseband_chip/btle-top-openlane-detailed-placement-cts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaoXianjun/BTLE/d431f70e4741b8f0e83c8d0ee50d14a5e5e6e63e/open_btle_baseband_chip/btle-top-openlane-detailed-placement-cts.png -------------------------------------------------------------------------------- /open_btle_baseband_chip/btle_controller_xilinx_7z020.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaoXianjun/BTLE/d431f70e4741b8f0e83c8d0ee50d14a5e5e6e63e/open_btle_baseband_chip/btle_controller_xilinx_7z020.jpg -------------------------------------------------------------------------------- /open_btle_baseband_chip/btle_rx_core-openlane-GDSII.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaoXianjun/BTLE/d431f70e4741b8f0e83c8d0ee50d14a5e5e6e63e/open_btle_baseband_chip/btle_rx_core-openlane-GDSII.png -------------------------------------------------------------------------------- /open_btle_baseband_chip/open_btle_baseband_chip_21_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaoXianjun/BTLE/d431f70e4741b8f0e83c8d0ee50d14a5e5e6e63e/open_btle_baseband_chip/open_btle_baseband_chip_21_1.png -------------------------------------------------------------------------------- /open_btle_baseband_chip/open_btle_baseband_chip_23_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaoXianjun/BTLE/d431f70e4741b8f0e83c8d0ee50d14a5e5e6e63e/open_btle_baseband_chip/open_btle_baseband_chip_23_1.png -------------------------------------------------------------------------------- /open_btle_baseband_chip/py-fig0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaoXianjun/BTLE/d431f70e4741b8f0e83c8d0ee50d14a5e5e6e63e/open_btle_baseband_chip/py-fig0.png -------------------------------------------------------------------------------- /open_btle_baseband_chip/py-fig1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaoXianjun/BTLE/d431f70e4741b8f0e83c8d0ee50d14a5e5e6e63e/open_btle_baseband_chip/py-fig1.png -------------------------------------------------------------------------------- /open_btle_baseband_chip/py-fig3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaoXianjun/BTLE/d431f70e4741b8f0e83c8d0ee50d14a5e5e6e63e/open_btle_baseband_chip/py-fig3.png -------------------------------------------------------------------------------- /open_btle_baseband_chip/py-fig4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaoXianjun/BTLE/d431f70e4741b8f0e83c8d0ee50d14a5e5e6e63e/open_btle_baseband_chip/py-fig4.png -------------------------------------------------------------------------------- /python/test_alignment_with_btle_sdr.py: -------------------------------------------------------------------------------- 1 | # Author: Xianjun Jiao 2 | # SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | # SPDX-License-Identifier: Apache-2.0 license 4 | 5 | import numpy as np 6 | # import matplotlib 7 | # matplotlib.use('TkAgg') 8 | import matplotlib.pyplot as plt 9 | 10 | import btlelib as bl 11 | 12 | import sys 13 | 14 | # #############################test vector generation method########################################### 15 | # Create btle_tx program by following https://github.com/JiaoXianjun/BTLE (sdr hardware is NOT needed!) 16 | # Run the example in README (An advertisement packet in channel 37): 17 | # # cd BTLE/host/build 18 | # # ./btle-tools/src/btle_tx 37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040506-LOCAL_NAME09-SDR/Bluetooth/Low/Energy r500 19 | # The pdu input to PHY is printed by btle_tx as: 20 | # # ... 21 | # # before crc24, pdu 22 | # # 422006050403020119095344522f426c7565746f6f74682f4c6f772f456e65726779 23 | # # ... 24 | # From the above btle_tx config and output, we can set 25 | # channel_number = 37 26 | # crc_state_init_bit = [] 27 | # pdu_bit_in_hex = '422006050403020119095344522f426c7565746f6f74682f4c6f772f456e65726779' 28 | # The btle_tx output IQ sample are in phy_sample.txt which will be compared with our python transmitter in btlelib.py 29 | 30 | # def test_alignment_with_btle_sdr(argv): 31 | if __name__ == "__main__": 32 | if len(sys.argv) == 1: 33 | example_idx = 0 34 | else: 35 | example_idx = int(sys.argv[1]) 36 | 37 | print('argument: example_idx') 38 | print(example_idx) 39 | 40 | if example_idx == 0: 41 | # ######################################### example 1 by: ########################################## 42 | print('Plese run firstly:') 43 | print('../host/build/btle-tools/src/btle_tx 37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040506-LOCAL_NAME09-SDR/Bluetooth/Low/Energy r500') 44 | channel_number = 37 # from the 1st field in above btle_tx command argument 45 | access_address = [] # will use default advertisement channel access address 0x8E89BED6 46 | crc_state_init_bit = [] # will use default advertisement channel crc init value 47 | pdu_bit_in_hex = '422006050403020119095344522f426c7565746f6f74682f4c6f772f456e65726779' 48 | elif example_idx == 1: 49 | # ######################################### example 2 by: ########################################## 50 | print('Plese run firstly:') 51 | print('../host/build/btle-tools/src/btle_tx 9-LL_CONNECTION_UPDATE_REQ-AA-60850A1B-LLID-3-NESN-0-SN-0-MD-0-WinSize-02-WinOffset-0e0F-Interval-0450-Latency-0607-Timeout-07D0-Instant-eeff-CRCInit-A77B22') 52 | channel_number = 9 # from the 1st field in above btle_tx command argument 53 | access_address = '1B0A8560' # due to byte order, the 60850A1B in above argument needs to be 1B0A8560 54 | crc_state_init_hex = 'A77B22' # from the CRCInit field in above btle_tx command argument 55 | crc_state_init_bit = bl.hex_string_to_bit(crc_state_init_hex) # from the CRCInit field in above btle_tx command argument 56 | pdu_bit_in_hex = '030c00020f0e50040706d007ffee' # from the output of above btle_tx command 57 | elif example_idx == 2: 58 | # ######################################### example 2 by: ########################################## 59 | print('Plese run firstly:') 60 | print('../host/build/btle-tools/src/btle_tx 10-LL_DATA-AA-11850A1B-LLID-1-NESN-0-SN-0-MD-0-DATA-XX-CRCInit-123456') 61 | channel_number = 10 # from the 1st field in above btle_tx command argument 62 | access_address = '1B0A8511' # due to byte order, the 11850A1B in above argument needs to be 1B0A8511 63 | crc_state_init_hex = '123456' # from the CRCInit field in above btle_tx command argument 64 | crc_state_init_bit = bl.hex_string_to_bit(crc_state_init_hex) # from the CRCInit field in above btle_tx command argument 65 | pdu_bit_in_hex = '0100' # from the output of above btle_tx command 66 | else: 67 | print('the argument example_idx needs to be 0, 1 or 2!') 68 | exit() 69 | 70 | # Start check alignment 71 | pdu_bit = bl.hex_string_to_bit(pdu_bit_in_hex) 72 | python_i, python_q, phy_bit, phy_bit_upsample = bl.btle_tx(pdu_bit, channel_number, crc_state_init_bit, access_address) 73 | 74 | btle_tx_sample = np.loadtxt('phy_sample.txt', dtype=np.int8) 75 | btle_i = btle_tx_sample[0::2] 76 | btle_q = btle_tx_sample[1::2] 77 | 78 | btle_fo, _ = bl.check_realtime_fo(btle_i, btle_q, 4) # in btle_tx C program, 4x oversampling is used. the python use 8x by default 79 | python_fo, _ = bl.check_realtime_fo(python_i, python_q) # no input means 8x oversampling is assumed 80 | 81 | plt.figure(0) 82 | plt.plot(btle_fo[2:], 'b', label='sdr btle_tx') 83 | plt.plot(python_fo[0::2], 'r.', label='python btlelib') # decimate to 4x oversampling 84 | plt.legend(loc="upper right") 85 | plt.title('btle_tx C sdr VS python btlelib. example '+str(example_idx)) 86 | plt.xlabel('sample idx') 87 | plt.ylabel('freq offset (normalized)') 88 | plt.grid() 89 | plt.show() 90 | 91 | np.savetxt('btle_fo.txt', btle_fo, fmt='%f') 92 | np.savetxt('python_fo.txt', python_fo, fmt='%f') 93 | -------------------------------------------------------------------------------- /python/test_btle_ber.py: -------------------------------------------------------------------------------- 1 | # Author: Xianjun Jiao 2 | # SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | # SPDX-License-Identifier: Apache-2.0 license 4 | 5 | import numpy as np 6 | # import matplotlib 7 | # matplotlib.use('TkAgg') 8 | import matplotlib.pyplot as plt 9 | 10 | import btlelib as bl 11 | 12 | import sys 13 | 14 | if __name__ == "__main__": 15 | if len(sys.argv) == 1: 16 | ppm_value = 0 17 | else: 18 | ppm_value = float(sys.argv[1]) 19 | if ppm_value > 50.0: 20 | print('ppm_value input should be within -50 ~ 50!') 21 | exit() 22 | 23 | print('argument: ppm_value') 24 | print(ppm_value) 25 | 26 | channel_number = 37 27 | pdu_bit_in_hex = '422506050403020119095344522f426c7565746f6f74682f4c6f772f456e657267791234567890' # ADV payload length 37. pdu len = 37+2=39 (maximum) 28 | 29 | ppm_abs = np.array([0, 10, 20, 25, 30, 35, 40, 45, 50]) 30 | max_snr = np.array([11, 12, 13, 14, 15, 17, 19, 21, 26]) 31 | snr = np.interp(np.abs(ppm_value), ppm_abs, max_snr) 32 | 33 | snr_set = [snr-4, snr-2.5, snr-1, snr] 34 | ber_set = [-1, -1, -1, -1] 35 | pkt_count_set = [100, 200, 300, 300] 36 | print('snr_set ', snr_set) 37 | print('pkt_count_set ', pkt_count_set) 38 | 39 | snr_idx = 0 40 | for snr in snr_set: 41 | # num_pkt_total = 0 42 | # num_pkt_err = 0 43 | 44 | num_bit_total = 0 45 | num_bit_err = 0 46 | 47 | for idx in range(pkt_count_set[snr_idx]): 48 | pdu_bit = bl.hex_string_to_bit(pdu_bit_in_hex) 49 | pdu_bit[16:] = np.int8(np.random.randint(2, size=len(pdu_bit)-16)) # generate random payload 50 | 51 | # generate tx packet iq sample 52 | tx_i, tx_q, _, _ = bl.btle_tx(pdu_bit, channel_number) 53 | 54 | # add sampling frequency offset, carrier frequency offset 55 | tx_i_error, tx_q_error, _, fo = bl.add_freq_sampling_error(tx_i, tx_q, ppm_value) 56 | 57 | # add AWGN noise 58 | rx_i, rx_q = bl.add_noise(tx_i_error, tx_q_error, snr) 59 | 60 | # receiver decodes signal from channel 61 | rx_pdu_bit, crc_ok, _, _, _, _, _ = bl.btle_rx(rx_i, rx_q, channel_number) 62 | 63 | # num_pkt_total = num_pkt_total + 1 64 | num_bit_total = num_bit_total + len(pdu_bit) 65 | 66 | if not crc_ok: 67 | # num_pkt_err = num_pkt_err + 1 68 | if len(rx_pdu_bit) == 0: 69 | num_bit_err = num_bit_err + len(pdu_bit) 70 | else: 71 | min_len = min(len(pdu_bit), len(rx_pdu_bit)) 72 | num_bit_err = num_bit_err + np.sum(pdu_bit[0:min_len] != rx_pdu_bit[0:min_len]) 73 | 74 | ber = num_bit_err/num_bit_total 75 | print('ppm ', ppm_value, ' freq offset ', fo, 'Hz snr ', snr, 'dB ber ', ber, ' num_bit_total ', num_bit_total, ' num_bit_err ', num_bit_err) 76 | # per = num_pkt_err/num_pkt_total 77 | # print('per ', per, ' num_pkt_total ', num_pkt_total, ' num_pkt_err ', num_pkt_err) 78 | 79 | ber_set[snr_idx] = ber 80 | snr_idx = snr_idx + 1 81 | 82 | plt.figure(0) 83 | plt.semilogy(snr_set, ber_set, 'b+-') 84 | plt.title('BER (Bit Error Rate) with ppm '+str(ppm_value)) 85 | plt.xlabel('SNR(dB)') 86 | plt.ylabel('BER') 87 | plt.grid() 88 | plt.show() 89 | 90 | np.savetxt('snr_set.txt', snr_set, fmt='%f') 91 | np.savetxt('ber_set.txt', ber_set, fmt='%f') 92 | -------------------------------------------------------------------------------- /usrp_replay_example/README.md: -------------------------------------------------------------------------------- 1 | ./btle_tx welcom_packets_discovery.txt 2 | 3 | copy above command generated IQ_sample_for_matlab.txt into variable "c" of gen_float32_bin_for_usrp_replay.m. 4 | 5 | run .m script in matlab or octave 6 | 7 | replay above script generated btle_ch37_iq_float32_welcom_msg.bin in replay_for_btle_4Msps.grc. 8 | 9 | Install LightBlue in your iPhone or other similar things of Android, and open the App. 10 | 11 | You will see a welcome message "SDR Bluetooth LE welcome u!" on your phone. 12 | -------------------------------------------------------------------------------- /usrp_replay_example/btle_ch37_iq_float32_welcom_msg.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaoXianjun/BTLE/d431f70e4741b8f0e83c8d0ee50d14a5e5e6e63e/usrp_replay_example/btle_ch37_iq_float32_welcom_msg.bin -------------------------------------------------------------------------------- /usrp_replay_example/welcom_packets_discovery.txt: -------------------------------------------------------------------------------- 1 | # example 2 | # ./btle_tx 37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040506-FLAGS-02-LOCAL_NAME09-CA-TXPOWER-03-SERVICE03-180D1810-SERVICE_DATA-180D40-MANUF_DATA-0001FF-CONN_INTERVAL-0006 (-SERVICE_SOLI14-1811) 3 | # FLAGS: 0x01 LE Limited Discoverable Mode; 0x02 LE General Discoverable Mode 4 | # SERVICE: 5 | # 0x02 16-bit Service UUIDs More 16-bit UUIDs available 6 | # 0x03 16-bit Service UUIDs Complete list of 16-bit UUIDs available 7 | # 0x04 32-bit Service UUIDs More 32-bit UUIDs available 8 | # 0x05 32-bit Service UUIDs Complete list of 32-bit UUIDs available 9 | # 0x06 128-bit Service UUIDs More 128-bit UUIDs available 10 | # 0x07 128-bit Service UUIDs Complete list of 128-bit UUIDs available 11 | 12 | # 37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040506-FLAGS-02-LOCAL_NAME09-Jxj-TXPOWER-03-SERVICE03-180D1810-SERVICE_DATA-180D40-MANUF_DATA-004CFF-CONN_INTERVAL-0006 13 | 14 | # r30 15 | 16 | 37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040506-LOCAL_NAME09-SDR Bluetooth LE welcome u! 17 | 18 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040500-LOCAL_NAME09-CA0000 11950 22.626 113.823 1 19 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040501-LOCAL_NAME09-CA0001 11950 22.626 113.823 1 20 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040502-LOCAL_NAME09-CA0002 11950 22.626 113.823 1 21 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040503-LOCAL_NAME09-CA0003 11950 22.626 113.823 1 22 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040504-LOCAL_NAME09-CA0004 11950 22.626 113.823 1 23 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040505-LOCAL_NAME09-CA0005 11950 22.626 113.823 1 24 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040506-LOCAL_NAME09-CA0006 11950 22.626 113.823 1 25 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040507-LOCAL_NAME09-CA0007 11950 22.626 113.823 1 26 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040508-LOCAL_NAME09-CA0008 11950 22.626 113.823 1 27 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040509-LOCAL_NAME09-CA0009 11950 22.626 113.823 1 28 | 29 | r40 30 | 31 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040506-LOCAL_NAME09-01234567890123456789012345678 32 | 33 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040506-FLAGS-02-LOCAL_NAME09-01234567890123456789012345 34 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-110203040506-FLAGS-02-LOCAL_NAME09-11234567890123456789012345 35 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-210203040506-FLAGS-02-LOCAL_NAME09-21234567890123456789012345 36 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-310203040506-FLAGS-02-LOCAL_NAME09-31234567890123456789012345 37 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-410203040506-FLAGS-02-LOCAL_NAME09-41234567890123456789012345 38 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-510203040506-FLAGS-02-LOCAL_NAME09-51234567890123456789012345 39 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-610203040506-FLAGS-02-LOCAL_NAME09-61234567890123456789012345 40 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-710203040506-FLAGS-02-LOCAL_NAME09-71234567890123456789012345 41 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-810203040506-FLAGS-02-LOCAL_NAME09-81234567890123456789012345 42 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-910203040506-FLAGS-02-LOCAL_NAME09-91234567890123456789012345 43 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-a10203040506-FLAGS-02-LOCAL_NAME09-a1234567890123456789012345 44 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-b10203040506-FLAGS-02-LOCAL_NAME09-b1234567890123456789012345 45 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-c10203040506-FLAGS-02-LOCAL_NAME09-c1234567890123456789012345 46 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-d10203040506-FLAGS-02-LOCAL_NAME09-d1234567890123456789012345 47 | 48 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-010203040506-FLAGS-02-SERVICE03-180D-SERVICE_DATA-180D40-SPACE-500 49 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-110203040506-FLAGS-02-SERVICE03-1819-SERVICE_DATA-181940-SPACE-100 50 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-210203040506-FLAGS-02-SERVICE03-181c-SERVICE_DATA-181c40-SPACE-500 51 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-310203040506-FLAGS-02-SERVICE03-180a-SERVICE_DATA-180a40-SPACE-500 52 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-410203040506-FLAGS-02-SERVICE03-1800-SERVICE_DATA-180040-SPACE-500 53 | #37-DISCOVERY-TxAdd-1-RxAdd-0-AdvA-410203040506-FLAGS-02-SERVICE03-1801-SERVICE_DATA-180140-SPACE-500 54 | # r30 55 | 56 | -------------------------------------------------------------------------------- /verilog/bit_repeat_upsample.v: -------------------------------------------------------------------------------- 1 | // Author: Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | // Input phy_bit rate 1M, output phy_bit rate 8M 6 | // clk speed 16M 7 | 8 | `timescale 1ns / 1ps 9 | module bit_repeat_upsample # 10 | ( 11 | parameter SAMPLE_PER_SYMBOL = 8 12 | ) ( 13 | input wire clk, 14 | input wire rst, 15 | 16 | input wire phy_bit, 17 | input wire bit_valid, 18 | input wire bit_valid_last, 19 | 20 | output reg bit_upsample, 21 | output wire bit_upsample_valid, 22 | output wire bit_upsample_valid_last 23 | ); 24 | 25 | reg [14:0] bit_valid_delay; 26 | reg [14:0] bit_valid_last_delay; 27 | wire bit_valid_wide; 28 | wire bit_valid_last_wide; 29 | reg bit_upsample_valid_internal; 30 | reg [2:0] bit_upsample_count; 31 | reg first_bit_valid_encountered; 32 | 33 | assign bit_valid_wide = (|bit_valid_delay); 34 | assign bit_valid_last_wide = (|bit_valid_last_delay); 35 | 36 | assign bit_upsample_valid = (bit_upsample_valid_internal & bit_valid_wide); 37 | assign bit_upsample_valid_last = ((bit_upsample_count==0) & bit_valid_last_wide); 38 | 39 | always @ (posedge clk) begin 40 | if (rst) begin 41 | bit_valid_delay <= 0; 42 | bit_valid_last_delay <= 0; 43 | bit_upsample <= 0; 44 | bit_upsample_valid_internal <= 0; 45 | bit_upsample_count <= 0; 46 | 47 | first_bit_valid_encountered <= 0; 48 | end else begin 49 | bit_valid_delay[0] <= bit_valid; 50 | bit_valid_delay[14:1] <= bit_valid_delay[13:0]; 51 | // bit_valid_delay[1] <= bit_valid_delay[0]; 52 | // bit_valid_delay[2] <= bit_valid_delay[1]; 53 | // bit_valid_delay[3] <= bit_valid_delay[2]; 54 | // bit_valid_delay[4] <= bit_valid_delay[3]; 55 | // bit_valid_delay[5] <= bit_valid_delay[4]; 56 | // bit_valid_delay[6] <= bit_valid_delay[5]; 57 | // bit_valid_delay[7] <= bit_valid_delay[6]; 58 | // bit_valid_delay[8] <= bit_valid_delay[7]; 59 | // bit_valid_delay[9] <= bit_valid_delay[8]; 60 | // bit_valid_delay[10] <= bit_valid_delay[9]; 61 | // bit_valid_delay[11] <= bit_valid_delay[10]; 62 | // bit_valid_delay[12] <= bit_valid_delay[11]; 63 | // bit_valid_delay[13] <= bit_valid_delay[12]; 64 | // bit_valid_delay[14] <= bit_valid_delay[13]; 65 | 66 | bit_valid_last_delay[0] <= bit_valid_last; 67 | bit_valid_last_delay[14:1] <= bit_valid_last_delay[13:0]; 68 | 69 | if (bit_valid) begin 70 | bit_upsample <= phy_bit; 71 | end 72 | bit_upsample_valid_internal <= (~bit_upsample_valid_internal); 73 | 74 | first_bit_valid_encountered <= (bit_valid? 1 : first_bit_valid_encountered); 75 | if (first_bit_valid_encountered == 0) begin 76 | bit_upsample_count <= 1; 77 | end else begin 78 | bit_upsample_count <= (bit_upsample_valid_internal == 0? (bit_upsample_count + 1) : bit_upsample_count); 79 | end 80 | end 81 | end 82 | 83 | endmodule 84 | 85 | -------------------------------------------------------------------------------- /verilog/bit_repeat_upsample_tb.v: -------------------------------------------------------------------------------- 1 | // Author: Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | // To generate test vector: 6 | // Create bit_repeat_upsample_test_input.txt with 1 bit (0 or 1) per line 7 | // Run verilog simulation: 8 | // iverilog -o bit_repeat_upsample_tb bit_repeat_upsample_tb.v bit_repeat_upsample.v 9 | // vvp bit_repeat_upsample_tb 10 | // Then remove the "// address " comment lines form file generated by writememh() 11 | // grep -v // bit_repeat_upsample_test_output.txt > new.txt 12 | // Each bit in the _test_input.txt will be repeated 8 times 13 | 14 | // ATTENTION: NUM_BIT_INPUT needs to be equal to the number of lines in bit_repeat_upsample_test_input.txt 15 | `timescale 1ns / 1ps 16 | module bit_repeat_upsample_tb # 17 | ( 18 | parameter SAMPLE_PER_SYMBOL = 8, 19 | parameter NUM_BIT_INPUT = 11 20 | ) ( 21 | ); 22 | 23 | reg clk; 24 | reg rst; 25 | 26 | reg [0:0] bit_repeat_upsample_test_input_mem [0:4095]; 27 | reg [0:0] bit_repeat_upsample_test_output_mem [0:4095]; 28 | initial begin 29 | $dumpfile("bit_repeat_upsample_tb.vcd"); 30 | $dumpvars; 31 | $readmemh("bit_repeat_upsample_test_input.txt", bit_repeat_upsample_test_input_mem); 32 | 33 | clk = 0; 34 | rst = 0; 35 | 36 | #200 rst = 1; 37 | 38 | #200 rst = 0; 39 | end 40 | 41 | always begin 42 | #((1000.0/16.0)/2.0) clk = !clk; //16MHz 43 | end 44 | 45 | reg bit; 46 | reg bit_valid; 47 | reg bit_valid_last; 48 | 49 | wire bit_upsample; 50 | wire bit_upsample_valid; 51 | wire bit_upsample_valid_last; 52 | 53 | // test process 54 | reg [31:0] clk_count; 55 | reg [31:0] info_bit_count; 56 | reg [31:0] bit_out_count; 57 | always @ (posedge clk) begin 58 | if (rst) begin 59 | bit <= 0; 60 | bit_valid <= 0; 61 | 62 | clk_count <= 1; 63 | info_bit_count <= 0; 64 | bit_out_count <= 0; 65 | end else begin 66 | clk_count <= clk_count + 1; 67 | 68 | if (clk_count[3:0] == 0) begin // speed 1M 69 | if (info_bit_count < NUM_BIT_INPUT) begin 70 | bit <= bit_repeat_upsample_test_input_mem[info_bit_count]; 71 | bit_valid <= 1; 72 | // $display("%h", bit_repeat_upsample_test_input_mem[info_bit_count]); 73 | if (info_bit_count == (NUM_BIT_INPUT-1)) begin 74 | bit_valid_last <= 1; 75 | end 76 | end 77 | info_bit_count <= info_bit_count + 1; 78 | end else begin 79 | bit_valid <= 0; 80 | bit_valid_last <= 0; 81 | end 82 | 83 | if (info_bit_count == (NUM_BIT_INPUT+30)) begin 84 | $display("%d input", NUM_BIT_INPUT); 85 | $display("%d output", bit_out_count); 86 | $writememh("bit_repeat_upsample_test_output.txt", bit_repeat_upsample_test_output_mem, 0, bit_out_count-1); 87 | $display("Please compare bit_repeat_upsample_test_output.txt and bit_repeat_upsample_test_input.txt"); 88 | $finish; 89 | end 90 | 91 | // record the result 92 | if (bit_upsample_valid) begin 93 | bit_repeat_upsample_test_output_mem[bit_out_count] <= bit_upsample; 94 | bit_out_count <= bit_out_count + 1; 95 | end 96 | end 97 | end 98 | 99 | bit_repeat_upsample # ( 100 | .SAMPLE_PER_SYMBOL(SAMPLE_PER_SYMBOL) 101 | ) bit_repeat_upsample_i ( 102 | .clk(clk), 103 | .rst(rst), 104 | 105 | .phy_bit(bit), 106 | .bit_valid(bit_valid), 107 | .bit_valid_last(bit_valid_last), 108 | 109 | .bit_upsample(bit_upsample), 110 | .bit_upsample_valid(bit_upsample_valid), 111 | .bit_upsample_valid_last(bit_upsample_valid_last) 112 | ); 113 | 114 | endmodule 115 | 116 | -------------------------------------------------------------------------------- /verilog/bit_repeat_upsample_test_input.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 1 3 | 0 4 | 1 5 | 0 6 | 1 7 | 0 8 | 1 9 | 0 10 | 0 11 | 0 12 | 13 | -------------------------------------------------------------------------------- /verilog/btle_controller_wrapper.xdc: -------------------------------------------------------------------------------- 1 | # Author: Xianjun Jiao 2 | # SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | # SPDX-License-Identifier: Apache-2.0 license 4 | 5 | create_clock -period 62.500 -name clk -waveform {0.000 31.250} [get_ports clk] 6 | set_input_delay -clock [get_clocks clk] -min -add_delay 10.000 [get_ports {rx_i_signal[*]}] 7 | set_input_delay -clock [get_clocks clk] -max -add_delay 20.000 [get_ports {rx_i_signal[*]}] 8 | set_input_delay -clock [get_clocks clk] -min -add_delay 10.000 [get_ports {rx_q_signal[*]}] 9 | set_input_delay -clock [get_clocks clk] -max -add_delay 20.000 [get_ports {rx_q_signal[*]}] 10 | set_input_delay -clock [get_clocks clk] -min -add_delay 10.000 [get_ports baremetal_phy_intf_mode] 11 | set_input_delay -clock [get_clocks clk] -max -add_delay 20.000 [get_ports baremetal_phy_intf_mode] 12 | set_input_delay -clock [get_clocks clk] -min -add_delay 10.000 [get_ports rst] 13 | set_input_delay -clock [get_clocks clk] -max -add_delay 20.000 [get_ports rst] 14 | set_input_delay -clock [get_clocks clk] -min -add_delay 10.000 [get_ports rx_iq_valid] 15 | set_input_delay -clock [get_clocks clk] -max -add_delay 20.000 [get_ports rx_iq_valid] 16 | set_input_delay -clock [get_clocks clk] -min -add_delay 10.000 [get_ports uart_rx] 17 | set_input_delay -clock [get_clocks clk] -max -add_delay 20.000 [get_ports uart_rx] 18 | set_output_delay -clock [get_clocks clk] -min -add_delay 5.000 [get_ports {tx_i_signal[*]}] 19 | set_output_delay -clock [get_clocks clk] -max -add_delay 11.000 [get_ports {tx_i_signal[*]}] 20 | set_output_delay -clock [get_clocks clk] -min -add_delay 5.000 [get_ports {tx_q_signal[*]}] 21 | set_output_delay -clock [get_clocks clk] -max -add_delay 11.000 [get_ports {tx_q_signal[*]}] 22 | set_output_delay -clock [get_clocks clk] -min -add_delay 5.000 [get_ports tx_iq_valid] 23 | set_output_delay -clock [get_clocks clk] -max -add_delay 11.000 [get_ports tx_iq_valid] 24 | set_output_delay -clock [get_clocks clk] -min -add_delay 5.000 [get_ports tx_iq_valid_last] 25 | set_output_delay -clock [get_clocks clk] -max -add_delay 11.000 [get_ports tx_iq_valid_last] 26 | set_output_delay -clock [get_clocks clk] -min -add_delay 5.000 [get_ports uart_tx] 27 | set_output_delay -clock [get_clocks clk] -max -add_delay 11.000 [get_ports uart_tx] 28 | 29 | set_property BITSTREAM.General.UnconstrainedPins {Allow} [current_design] 30 | -------------------------------------------------------------------------------- /verilog/btle_phy.v: -------------------------------------------------------------------------------- 1 | // Author: Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | // iverilog -o btle_phy btle_phy.v btle_rx.v btle_rx_core_tb.v btle_rx_core.v gfsk_demodulation.v search_unique_bit_sequence.v scramble_core.v crc24_core.v serial_in_ram_out.v dpram.v btle_tx.v crc24.v scramble.v gfsk_modulation.v bit_repeat_upsample.v gauss_filter.v vco.v 6 | 7 | `timescale 1ns / 1ps 8 | module btle_phy # 9 | ( 10 | parameter CRC_STATE_BIT_WIDTH = 24, 11 | parameter CHANNEL_NUMBER_BIT_WIDTH = 6, 12 | parameter SAMPLE_PER_SYMBOL = 8, 13 | parameter GAUSS_FILTER_BIT_WIDTH = 16, 14 | parameter NUM_TAP_GAUSS_FILTER = 17, 15 | parameter VCO_BIT_WIDTH = 16, 16 | parameter SIN_COS_ADDR_BIT_WIDTH = 11, 17 | parameter IQ_BIT_WIDTH = 8, 18 | parameter GAUSS_FIR_OUT_AMP_SCALE_DOWN_NUM_BIT_SHIFT = 1, 19 | 20 | parameter GFSK_DEMODULATION_BIT_WIDTH = 16, 21 | parameter LEN_UNIQUE_BIT_SEQUENCE = 32 22 | ) ( 23 | input wire clk, 24 | input wire rst, 25 | 26 | // for tx 27 | input wire [3:0] tx_gauss_filter_tap_index, // only need to set 0~8, 9~16 will be mirror of 0~7 28 | input wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tx_gauss_filter_tap_value, 29 | 30 | input wire [(SIN_COS_ADDR_BIT_WIDTH-1) : 0] tx_cos_table_write_address, 31 | input wire signed [(IQ_BIT_WIDTH-1) : 0] tx_cos_table_write_data, 32 | input wire [(SIN_COS_ADDR_BIT_WIDTH-1) : 0] tx_sin_table_write_address, 33 | input wire signed [(IQ_BIT_WIDTH-1) : 0] tx_sin_table_write_data, 34 | 35 | input wire [7:0] tx_preamble, 36 | 37 | input wire [31:0] tx_access_address, 38 | input wire [(CRC_STATE_BIT_WIDTH-1) : 0] tx_crc_state_init_bit, 39 | input wire tx_crc_state_init_bit_load, 40 | input wire [(CHANNEL_NUMBER_BIT_WIDTH-1) : 0] tx_channel_number, 41 | input wire tx_channel_number_load, 42 | 43 | input wire [7:0] tx_pdu_octet_mem_data, 44 | input wire [5:0] tx_pdu_octet_mem_addr, 45 | 46 | input wire tx_start, 47 | 48 | output wire signed [(IQ_BIT_WIDTH-1) : 0] tx_i_signal, 49 | output wire signed [(IQ_BIT_WIDTH-1) : 0] tx_q_signal, 50 | output wire tx_iq_valid, 51 | output wire tx_iq_valid_last, 52 | 53 | // for tx debug purpose 54 | output wire tx_phy_bit, 55 | output wire tx_phy_bit_valid, 56 | output wire tx_phy_bit_valid_last, 57 | 58 | output wire tx_bit_upsample, 59 | output wire tx_bit_upsample_valid, 60 | output wire tx_bit_upsample_valid_last, 61 | 62 | output wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tx_bit_upsample_gauss_filter, 63 | output wire tx_bit_upsample_gauss_filter_valid, 64 | output wire tx_bit_upsample_gauss_filter_valid_last, 65 | 66 | // for rx 67 | input wire [(LEN_UNIQUE_BIT_SEQUENCE-1) : 0] rx_unique_bit_sequence, 68 | input wire [(CHANNEL_NUMBER_BIT_WIDTH-1) : 0] rx_channel_number, 69 | input wire [(CRC_STATE_BIT_WIDTH-1) : 0] rx_crc_state_init_bit, 70 | 71 | input wire signed [(GFSK_DEMODULATION_BIT_WIDTH-1) : 0] rx_i_signal, 72 | input wire signed [(GFSK_DEMODULATION_BIT_WIDTH-1) : 0] rx_q_signal, 73 | input wire rx_iq_valid, 74 | 75 | output wire rx_hit_flag, 76 | output wire rx_decode_run, 77 | output wire rx_decode_end, 78 | output wire rx_crc_ok, 79 | output wire [2:0] rx_best_phase, 80 | output wire [6:0] rx_payload_length, 81 | 82 | input wire [5:0] rx_pdu_octet_mem_addr, 83 | output wire [7:0] rx_pdu_octet_mem_data 84 | ); 85 | 86 | btle_tx # ( 87 | .CRC_STATE_BIT_WIDTH(CRC_STATE_BIT_WIDTH), 88 | .CHANNEL_NUMBER_BIT_WIDTH(CHANNEL_NUMBER_BIT_WIDTH), 89 | .SAMPLE_PER_SYMBOL(SAMPLE_PER_SYMBOL), 90 | .GAUSS_FILTER_BIT_WIDTH(GAUSS_FILTER_BIT_WIDTH), 91 | .NUM_TAP_GAUSS_FILTER(NUM_TAP_GAUSS_FILTER), 92 | .VCO_BIT_WIDTH(VCO_BIT_WIDTH), 93 | .SIN_COS_ADDR_BIT_WIDTH(SIN_COS_ADDR_BIT_WIDTH), 94 | .IQ_BIT_WIDTH(IQ_BIT_WIDTH), 95 | .GAUSS_FIR_OUT_AMP_SCALE_DOWN_NUM_BIT_SHIFT(GAUSS_FIR_OUT_AMP_SCALE_DOWN_NUM_BIT_SHIFT) 96 | ) btle_tx_i ( 97 | .clk(clk), 98 | .rst(rst), 99 | 100 | .gauss_filter_tap_index(tx_gauss_filter_tap_index), 101 | .gauss_filter_tap_value(tx_gauss_filter_tap_value), 102 | 103 | .cos_table_write_address(tx_cos_table_write_address), 104 | .cos_table_write_data(tx_cos_table_write_data), 105 | .sin_table_write_address(tx_sin_table_write_address), 106 | .sin_table_write_data(tx_sin_table_write_data), 107 | 108 | .preamble(tx_preamble), 109 | 110 | .access_address(tx_access_address), 111 | .crc_state_init_bit(tx_crc_state_init_bit), 112 | .crc_state_init_bit_load(tx_crc_state_init_bit_load), 113 | .channel_number(tx_channel_number), 114 | .channel_number_load(tx_channel_number_load), 115 | 116 | .pdu_octet_mem_data(tx_pdu_octet_mem_data), 117 | .pdu_octet_mem_addr(tx_pdu_octet_mem_addr), 118 | 119 | .tx_start(tx_start), 120 | 121 | .i(tx_i_signal), 122 | .q(tx_q_signal), 123 | .iq_valid(tx_iq_valid), 124 | .iq_valid_last(tx_iq_valid_last), 125 | 126 | // for debug purpose 127 | .phy_bit(tx_phy_bit), 128 | .phy_bit_valid(tx_phy_bit_valid), 129 | .phy_bit_valid_last(tx_phy_bit_valid_last), 130 | 131 | .bit_upsample(tx_bit_upsample), 132 | .bit_upsample_valid(tx_bit_upsample_valid), 133 | .bit_upsample_valid_last(tx_bit_upsample_valid_last), 134 | 135 | .bit_upsample_gauss_filter(tx_bit_upsample_gauss_filter), 136 | .bit_upsample_gauss_filter_valid(tx_bit_upsample_gauss_filter_valid), 137 | .bit_upsample_gauss_filter_valid_last(tx_bit_upsample_gauss_filter_valid_last) 138 | ); 139 | 140 | btle_rx # ( 141 | .SAMPLE_PER_SYMBOL(SAMPLE_PER_SYMBOL), 142 | .GFSK_DEMODULATION_BIT_WIDTH(GFSK_DEMODULATION_BIT_WIDTH), 143 | .LEN_UNIQUE_BIT_SEQUENCE(LEN_UNIQUE_BIT_SEQUENCE), 144 | .CHANNEL_NUMBER_BIT_WIDTH(CHANNEL_NUMBER_BIT_WIDTH), 145 | .CRC_STATE_BIT_WIDTH(CRC_STATE_BIT_WIDTH) 146 | ) btle_rx_i ( 147 | .clk(clk), 148 | .rst(rst), 149 | 150 | .unique_bit_sequence(rx_unique_bit_sequence), 151 | .channel_number(rx_channel_number), 152 | .crc_state_init_bit(rx_crc_state_init_bit), 153 | 154 | .i(rx_i_signal), 155 | .q(rx_q_signal), 156 | .iq_valid(rx_iq_valid), 157 | 158 | .hit_flag(rx_hit_flag), 159 | .decode_run(rx_decode_run), 160 | .decode_end(rx_decode_end), 161 | .crc_ok(rx_crc_ok), 162 | .best_phase(rx_best_phase), 163 | 164 | .payload_length(rx_payload_length), 165 | 166 | .pdu_octet_mem_data(rx_pdu_octet_mem_data), 167 | .pdu_octet_mem_addr(rx_pdu_octet_mem_addr) 168 | ); 169 | 170 | endmodule 171 | 172 | -------------------------------------------------------------------------------- /verilog/btle_rx_core.v: -------------------------------------------------------------------------------- 1 | // Author: Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | `timescale 1ns / 1ps 6 | module btle_rx_core # 7 | ( 8 | parameter GFSK_DEMODULATION_BIT_WIDTH = 16, 9 | parameter LEN_UNIQUE_BIT_SEQUENCE = 32, 10 | parameter CHANNEL_NUMBER_BIT_WIDTH = 6, 11 | parameter CRC_STATE_BIT_WIDTH = 24 12 | ) ( 13 | input wire clk, 14 | input wire rst, 15 | 16 | input wire [(LEN_UNIQUE_BIT_SEQUENCE-1) : 0] unique_bit_sequence, 17 | input wire [(CHANNEL_NUMBER_BIT_WIDTH-1) : 0] channel_number, 18 | input wire [(CRC_STATE_BIT_WIDTH-1) : 0] crc_state_init_bit, 19 | 20 | input wire signed [(GFSK_DEMODULATION_BIT_WIDTH-1) : 0] i, 21 | input wire signed [(GFSK_DEMODULATION_BIT_WIDTH-1) : 0] q, 22 | input wire iq_valid, 23 | 24 | output wire hit_flag, 25 | output reg [6:0] payload_length, 26 | output reg payload_length_valid, 27 | 28 | output wire info_bit, 29 | output wire bit_valid, 30 | 31 | output reg [7:0] octet, 32 | output reg octet_valid, 33 | 34 | output reg decode_end, 35 | output reg crc_ok 36 | ); 37 | 38 | localparam [1:0] IDLE = 0, 39 | EXTRACT_LENGTH = 1, 40 | CHECK_CRC = 2; 41 | 42 | wire adv_pdu_flag; 43 | // wire hit_flag; 44 | wire phy_bit; 45 | wire phy_bit_valid; 46 | wire [(CRC_STATE_BIT_WIDTH-1) : 0] lfsr; 47 | wire [(CRC_STATE_BIT_WIDTH-1) : 0] crc24_bit; 48 | 49 | reg bit_valid_delay; 50 | reg [1:0] phy_rx_state; 51 | reg [9:0] bit_count; 52 | wire [6:0] octet_count; 53 | // reg [6:0] payload_length; 54 | 55 | assign adv_pdu_flag = (channel_number==37 || channel_number==38 || channel_number==39); 56 | 57 | assign octet_count = bit_count[9:3]; 58 | 59 | assign crc24_bit = lfsr; 60 | 61 | // state machine to extract payload length and check crc 62 | always @ (posedge clk) begin 63 | if (rst) begin 64 | bit_valid_delay <= 0; 65 | octet <= 0; 66 | octet_valid <= 0; 67 | bit_count <= 0; 68 | payload_length <= 0; 69 | payload_length_valid <= 0; 70 | decode_end <= 0; 71 | crc_ok <= 0; 72 | 73 | phy_rx_state <= IDLE; 74 | end else begin 75 | bit_valid_delay <= bit_valid; 76 | case(phy_rx_state) 77 | IDLE: begin 78 | octet <= 0; 79 | octet_valid <= 0; 80 | bit_count <= 0; 81 | payload_length <= 0; 82 | payload_length_valid <= 0; 83 | decode_end <= 0; 84 | crc_ok <= 0; 85 | 86 | phy_rx_state <= (hit_flag? EXTRACT_LENGTH : phy_rx_state); 87 | end 88 | 89 | EXTRACT_LENGTH: begin 90 | if (bit_valid) begin 91 | octet[7] <= info_bit; 92 | octet[6:0] <= octet[7:1]; 93 | 94 | bit_count <= bit_count + 1; 95 | end 96 | if (octet_count == 2) begin 97 | payload_length <= (adv_pdu_flag? octet[5:0] : octet[4:0]); 98 | payload_length_valid <= 1; 99 | bit_count <= 0; 100 | phy_rx_state <= CHECK_CRC; 101 | end 102 | octet_valid <= (octet_count>=1? (bit_valid_delay && bit_count[2:0] == 0) : octet_valid); 103 | end 104 | 105 | CHECK_CRC: begin 106 | payload_length_valid <= 0; 107 | if (bit_valid) begin 108 | octet[7] <= info_bit; 109 | octet[6:0] <= octet[7:1]; 110 | 111 | // $display("%d", info_bit); 112 | 113 | bit_count <= bit_count + 1; 114 | end 115 | 116 | if (octet_count == (payload_length+3)) begin 117 | // $display("payload_length %d", payload_length); 118 | // $display("crc24_bit %06h", crc24_bit); 119 | 120 | decode_end <= 1; 121 | crc_ok <= (crc24_bit == 0); 122 | 123 | phy_rx_state <= IDLE; 124 | end else if (octet_count >= 1 && octet_count <= payload_length) begin 125 | octet_valid <= (bit_valid_delay && bit_count[2:0] == 0); 126 | end else begin 127 | octet_valid <= 0; 128 | end 129 | end 130 | endcase 131 | end 132 | end 133 | 134 | gfsk_demodulation # ( 135 | .GFSK_DEMODULATION_BIT_WIDTH(GFSK_DEMODULATION_BIT_WIDTH) 136 | ) gfsk_demodulation_i ( 137 | .clk(clk), 138 | .rst(rst), 139 | 140 | .i(i), 141 | .q(q), 142 | .iq_valid(iq_valid), 143 | 144 | .signal_for_decision(), 145 | .signal_for_decision_valid(), 146 | 147 | .phy_bit(phy_bit), 148 | .bit_valid(phy_bit_valid) 149 | ); 150 | 151 | search_unique_bit_sequence # ( 152 | .LEN_UNIQUE_BIT_SEQUENCE(LEN_UNIQUE_BIT_SEQUENCE) 153 | ) search_unique_bit_sequence_i ( 154 | .clk(clk), 155 | .rst(rst), 156 | 157 | .phy_bit(phy_bit), 158 | .bit_valid(phy_bit_valid), 159 | .unique_bit_sequence(unique_bit_sequence), 160 | 161 | .hit_flag(hit_flag) 162 | ); 163 | 164 | scramble_core # ( 165 | .CHANNEL_NUMBER_BIT_WIDTH(CHANNEL_NUMBER_BIT_WIDTH) 166 | ) scramble_core_i ( 167 | .clk(clk), 168 | .rst(rst|hit_flag), 169 | 170 | .channel_number(channel_number), 171 | .channel_number_load(1'b0), 172 | .data_in(phy_bit), 173 | .data_in_valid(phy_bit_valid), 174 | 175 | .data_out(info_bit), 176 | .data_out_valid(bit_valid) 177 | ); 178 | 179 | crc24_core # ( 180 | .CRC_STATE_BIT_WIDTH(CRC_STATE_BIT_WIDTH) 181 | ) crc24_core_i ( 182 | .clk(clk), 183 | .rst(rst|hit_flag), 184 | 185 | .crc_state_init_bit(crc_state_init_bit), 186 | .crc_state_init_bit_load(1'b0), 187 | .data_in(info_bit), 188 | .data_in_valid(bit_valid), 189 | 190 | .lfsr(lfsr) 191 | ); 192 | 193 | endmodule 194 | 195 | -------------------------------------------------------------------------------- /verilog/btle_tx.v: -------------------------------------------------------------------------------- 1 | // Author: Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | // iverilog -o btle_tx btle_tx.v dpram.v crc24.v crc24_core.v scramble.v scramble_core.v gfsk_modulation.v bit_repeat_upsample.v gauss_filter.v vco.v 6 | 7 | `timescale 1ns / 1ps 8 | module btle_tx # 9 | ( 10 | parameter CRC_STATE_BIT_WIDTH = 24, 11 | parameter CHANNEL_NUMBER_BIT_WIDTH = 6, 12 | parameter SAMPLE_PER_SYMBOL = 8, 13 | parameter GAUSS_FILTER_BIT_WIDTH = 16, 14 | parameter NUM_TAP_GAUSS_FILTER = 17, 15 | parameter VCO_BIT_WIDTH = 16, 16 | parameter SIN_COS_ADDR_BIT_WIDTH = 11, 17 | parameter IQ_BIT_WIDTH = 8, 18 | parameter GAUSS_FIR_OUT_AMP_SCALE_DOWN_NUM_BIT_SHIFT = 1 19 | ) ( 20 | input wire clk, 21 | input wire rst, 22 | 23 | input wire [3:0] gauss_filter_tap_index, // only need to set 0~8, 9~16 will be mirror of 0~7 24 | input wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] gauss_filter_tap_value, 25 | 26 | input wire [(SIN_COS_ADDR_BIT_WIDTH-1) : 0] cos_table_write_address, 27 | input wire signed [(IQ_BIT_WIDTH-1) : 0] cos_table_write_data, 28 | input wire [(SIN_COS_ADDR_BIT_WIDTH-1) : 0] sin_table_write_address, 29 | input wire signed [(IQ_BIT_WIDTH-1) : 0] sin_table_write_data, 30 | 31 | input wire [7:0] preamble, 32 | 33 | input wire [31:0] access_address, 34 | input wire [(CRC_STATE_BIT_WIDTH-1) : 0] crc_state_init_bit, // load into lfsr (linear feedback shift register) upon crc_state_init_bit_load==1 35 | input wire crc_state_init_bit_load, 36 | input wire [(CHANNEL_NUMBER_BIT_WIDTH-1) : 0] channel_number, // load into lfsr (linear feedback shift register) upon channel_number_load==1 37 | input wire channel_number_load, 38 | 39 | input wire [7:0] pdu_octet_mem_data, 40 | input wire [5:0] pdu_octet_mem_addr, 41 | 42 | input wire tx_start, 43 | 44 | output wire signed [(IQ_BIT_WIDTH-1) : 0] i, 45 | output wire signed [(IQ_BIT_WIDTH-1) : 0] q, 46 | output wire iq_valid, 47 | output wire iq_valid_last, 48 | 49 | // for debug purpose 50 | output wire phy_bit, 51 | output wire phy_bit_valid, 52 | output wire phy_bit_valid_last, 53 | 54 | output wire bit_upsample, 55 | output wire bit_upsample_valid, 56 | output wire bit_upsample_valid_last, 57 | 58 | output wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] bit_upsample_gauss_filter, 59 | output wire bit_upsample_gauss_filter_valid, 60 | output wire bit_upsample_gauss_filter_valid_last 61 | ); 62 | 63 | localparam [1:0] IDLE = 0, 64 | TX_PREAMBLE_ACCESS = 1, 65 | TX_PDU = 2, 66 | WAIT_LAST_SAMPLE = 3; 67 | 68 | reg [1:0] phy_tx_state; 69 | reg [5:0] addr; 70 | wire [7:0] data; 71 | reg [7:0] octet; 72 | wire adv_pdu_flag; 73 | reg [6:0] payload_length; 74 | reg [9:0] bit_count; 75 | reg [5:0] bit_count_preamble_access; 76 | 77 | reg info_bit; 78 | reg info_bit_valid; 79 | reg info_bit_valid_last; 80 | 81 | reg [39:0] preamble_access_address; 82 | 83 | wire info_bit_after_crc24; 84 | wire info_bit_after_crc24_valid; 85 | wire info_bit_after_crc24_valid_last; 86 | 87 | // wire phy_bit; 88 | // wire phy_bit_valid; 89 | // wire phy_bit_valid_last; 90 | 91 | wire signed [(IQ_BIT_WIDTH-1) : 0] i_internal; 92 | wire signed [(IQ_BIT_WIDTH-1) : 0] q_internal; 93 | 94 | reg [6:0] clk_count; // assume clk speed 16M, baseband phy_bit rate 1M. octet rate 1/8M. need 128x clk speed down to read octet memory. 95 | 96 | assign adv_pdu_flag = (channel_number==37 || channel_number==38 || channel_number==39); 97 | 98 | assign i = (phy_tx_state == IDLE? 0 : i_internal); 99 | assign q = (phy_tx_state == IDLE? 0 : q_internal); 100 | 101 | // state machine to extract payload length and check crc 102 | always @ (posedge clk) begin 103 | if (rst) begin 104 | addr <= 0; 105 | octet <= 0; 106 | 107 | payload_length <= 0; 108 | bit_count_preamble_access <= 0; 109 | bit_count <= 0; 110 | 111 | preamble_access_address <= 0; 112 | info_bit <= 0; 113 | info_bit_valid <= 0; 114 | info_bit_valid_last <= 0; 115 | 116 | clk_count <= 0; 117 | 118 | phy_tx_state <= IDLE; 119 | end else begin 120 | // if (phy_bit_valid) begin 121 | // $display("%d", phy_bit); 122 | // end 123 | 124 | case(phy_tx_state) 125 | IDLE: begin 126 | addr <= 0; 127 | octet <= 0; 128 | 129 | payload_length <= 7'h7f; 130 | bit_count_preamble_access <= 0; 131 | bit_count <= 0; 132 | 133 | info_bit <= 0; 134 | info_bit_valid <= 0; 135 | info_bit_valid_last <= 0; 136 | 137 | clk_count <= 0; 138 | 139 | preamble_access_address <= (tx_start? {access_address, preamble} : preamble_access_address); 140 | phy_tx_state <= (tx_start? TX_PREAMBLE_ACCESS : phy_tx_state); 141 | end 142 | 143 | TX_PREAMBLE_ACCESS: begin 144 | clk_count <= clk_count + 1; 145 | if (clk_count[3:0] == 1) begin // speed 1M 146 | info_bit <= preamble_access_address[0]; 147 | info_bit_valid <= 1; 148 | preamble_access_address[38:0] <= preamble_access_address[39:1]; 149 | 150 | bit_count_preamble_access <= bit_count_preamble_access + 1; 151 | 152 | if (bit_count_preamble_access == (40 - 1)) begin 153 | phy_tx_state <= TX_PDU; 154 | end 155 | end else begin 156 | info_bit_valid <= 0; 157 | end 158 | end 159 | 160 | TX_PDU: begin 161 | clk_count <= clk_count + 1; 162 | if (clk_count == 0) begin // speed 1/8M 163 | addr <= addr + 1; 164 | octet <= data; 165 | end 166 | if (clk_count[3:0] == 1) begin // speed 1M 167 | info_bit <= octet[0]; 168 | info_bit_valid <= 1; 169 | octet[6:0] <= octet[7:1]; 170 | 171 | bit_count <= bit_count + 1; 172 | 173 | if (bit_count == ((payload_length+2)*8 - 1)) begin 174 | info_bit_valid_last <= 1; 175 | phy_tx_state <= WAIT_LAST_SAMPLE; 176 | end 177 | end else begin 178 | info_bit_valid <= 0; 179 | end 180 | 181 | if (addr == 2 && clk_count == 1) begin 182 | payload_length <= (adv_pdu_flag? octet[5:0] : octet[4:0]); 183 | end 184 | 185 | if (addr == 2 && clk_count == 2) begin 186 | $display("payload_length %d", payload_length); 187 | end 188 | end 189 | 190 | WAIT_LAST_SAMPLE: begin 191 | info_bit_valid <= 0; 192 | info_bit_valid_last <= 0; 193 | phy_tx_state <= (iq_valid_last? IDLE : phy_tx_state); 194 | end 195 | endcase 196 | end 197 | end 198 | 199 | dpram # ( 200 | .DATA_WIDTH(8), 201 | .ADDRESS_WIDTH(6) 202 | ) cos_table_dpram_i ( 203 | .clk(clk), 204 | .rst(rst), 205 | 206 | .write_address(pdu_octet_mem_addr), 207 | .write_data(pdu_octet_mem_data), 208 | .write_enable(1'b1), 209 | 210 | .read_address(addr), 211 | .read_data(data) 212 | ); 213 | 214 | crc24 # ( 215 | .CRC_STATE_BIT_WIDTH(CRC_STATE_BIT_WIDTH) 216 | ) crc24_i ( 217 | .clk(clk), 218 | .rst(rst), 219 | 220 | .crc_state_init_bit(crc_state_init_bit), 221 | .crc_state_init_bit_load(crc_state_init_bit_load), 222 | 223 | .info_bit(info_bit), 224 | .info_bit_valid(info_bit_valid), 225 | .info_bit_valid_last(info_bit_valid_last), 226 | 227 | .info_bit_after_crc24(info_bit_after_crc24), 228 | .info_bit_after_crc24_valid(info_bit_after_crc24_valid), 229 | .info_bit_after_crc24_valid_last(info_bit_after_crc24_valid_last) 230 | ); 231 | 232 | scramble # ( 233 | .CHANNEL_NUMBER_BIT_WIDTH(CHANNEL_NUMBER_BIT_WIDTH) 234 | ) scramble_i ( 235 | .clk(clk), 236 | .rst(rst), 237 | 238 | .channel_number(channel_number), 239 | .channel_number_load(channel_number_load), 240 | 241 | .data_in(info_bit_after_crc24), 242 | .data_in_valid(info_bit_after_crc24_valid), 243 | .data_in_valid_last(info_bit_after_crc24_valid_last), 244 | 245 | .data_out(phy_bit), 246 | .data_out_valid(phy_bit_valid), 247 | .data_out_valid_last(phy_bit_valid_last) 248 | ); 249 | 250 | gfsk_modulation # ( 251 | .SAMPLE_PER_SYMBOL(SAMPLE_PER_SYMBOL), 252 | .GAUSS_FILTER_BIT_WIDTH(GAUSS_FILTER_BIT_WIDTH), 253 | .NUM_TAP_GAUSS_FILTER(NUM_TAP_GAUSS_FILTER), 254 | .VCO_BIT_WIDTH(VCO_BIT_WIDTH), 255 | .SIN_COS_ADDR_BIT_WIDTH(SIN_COS_ADDR_BIT_WIDTH), 256 | .IQ_BIT_WIDTH(IQ_BIT_WIDTH), 257 | .GAUSS_FIR_OUT_AMP_SCALE_DOWN_NUM_BIT_SHIFT(GAUSS_FIR_OUT_AMP_SCALE_DOWN_NUM_BIT_SHIFT) 258 | ) gfsk_modulation_i ( 259 | .clk(clk), 260 | .rst(rst), 261 | 262 | .gauss_filter_tap_index(gauss_filter_tap_index), // only need to set 0~8, 9~16 will be mirror of 0~7 263 | .gauss_filter_tap_value(gauss_filter_tap_value), 264 | 265 | .cos_table_write_address(cos_table_write_address), 266 | .cos_table_write_data(cos_table_write_data), 267 | .sin_table_write_address(sin_table_write_address), 268 | .sin_table_write_data(sin_table_write_data), 269 | 270 | .phy_bit(phy_bit), 271 | .bit_valid(phy_bit_valid), 272 | .bit_valid_last(phy_bit_valid_last), 273 | 274 | .cos_out(i_internal), 275 | .sin_out(q_internal), 276 | .sin_cos_out_valid(iq_valid), 277 | .sin_cos_out_valid_last(iq_valid_last), 278 | 279 | .bit_upsample(bit_upsample), 280 | .bit_upsample_valid(bit_upsample_valid), 281 | .bit_upsample_valid_last(bit_upsample_valid_last), 282 | 283 | .bit_upsample_gauss_filter(bit_upsample_gauss_filter), 284 | .bit_upsample_gauss_filter_valid(bit_upsample_gauss_filter_valid), 285 | .bit_upsample_gauss_filter_valid_last(bit_upsample_gauss_filter_valid_last) 286 | ); 287 | 288 | endmodule 289 | 290 | -------------------------------------------------------------------------------- /verilog/crc24.v: -------------------------------------------------------------------------------- 1 | // Author: Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | // Core_v5.3 figure3.4 on page 2734 6 | // Assume clk speed 16M, info_bit 1M, info_bit_valid every 16 clk 7 | // CRC operation skips the 40 bits at the beginning (preamble+access_address) 8 | 9 | `timescale 1ns / 1ps 10 | module crc24 # 11 | ( 12 | parameter CRC_STATE_BIT_WIDTH = 24 13 | ) ( 14 | input wire clk, 15 | input wire rst, 16 | 17 | input wire [(CRC_STATE_BIT_WIDTH-1) : 0] crc_state_init_bit, // load into lfsr (linear feedback shift register) upon crc_state_init_bit_load==1 18 | input wire crc_state_init_bit_load, 19 | input wire info_bit, 20 | input wire info_bit_valid, 21 | input wire info_bit_valid_last, // if this is true together with valid, it means last bit input 22 | output reg info_bit_after_crc24, 23 | output reg info_bit_after_crc24_valid, 24 | output reg info_bit_after_crc24_valid_last // indicate last bit out together with info_bit_after_crc24_valid 25 | ); 26 | 27 | localparam [1:0] IDLE = 0, 28 | WORK_ON_INPUT = 1, 29 | CRC_BIT_OUTPUT = 2; 30 | 31 | reg [1:0] crc_state; 32 | 33 | wire [(CRC_STATE_BIT_WIDTH-1) : 0] lfsr; 34 | 35 | wire info_bit_valid_internal; 36 | reg [8:0] info_bit_count; 37 | reg [4:0] crc_bit_count; 38 | reg [3:0] clk_count; 39 | 40 | assign info_bit_valid_internal = (info_bit_count>=40? info_bit_valid : 0); 41 | 42 | always @ (posedge clk) begin 43 | if (rst) begin 44 | info_bit_after_crc24 <= 0; 45 | info_bit_after_crc24_valid <= 0; 46 | info_bit_after_crc24_valid_last <= 0; 47 | 48 | info_bit_count <= 0; 49 | crc_bit_count <= 0; 50 | clk_count <= 0; 51 | 52 | crc_state <= IDLE; 53 | end else begin 54 | case(crc_state) 55 | IDLE: begin 56 | info_bit_after_crc24 <= info_bit; 57 | info_bit_after_crc24_valid <= info_bit_valid; 58 | 59 | crc_bit_count <= 0; 60 | clk_count <= 0; 61 | 62 | info_bit_after_crc24_valid_last <= 0; 63 | 64 | info_bit_count <= (info_bit_valid ? (info_bit_count+1) : info_bit_count); 65 | 66 | crc_state <= (info_bit_valid ? WORK_ON_INPUT : crc_state); 67 | end 68 | 69 | WORK_ON_INPUT: begin 70 | info_bit_after_crc24 <= info_bit; 71 | info_bit_after_crc24_valid <= info_bit_valid; 72 | 73 | info_bit_count <= (info_bit_valid ? (info_bit_count+1) : info_bit_count); 74 | 75 | crc_state <= (info_bit_valid_last ? CRC_BIT_OUTPUT : crc_state); 76 | end 77 | 78 | CRC_BIT_OUTPUT: begin 79 | clk_count <= clk_count + 1; 80 | if (clk_count == 15) begin 81 | crc_bit_count <= crc_bit_count + 1; 82 | info_bit_after_crc24 <= lfsr[23-crc_bit_count]; 83 | info_bit_after_crc24_valid <= 1; 84 | if (crc_bit_count == 23) begin 85 | info_bit_after_crc24_valid_last <= 1; 86 | 87 | info_bit_count <= 0; 88 | 89 | crc_state <= IDLE; 90 | end 91 | end else begin 92 | info_bit_after_crc24_valid <= 0; 93 | info_bit_after_crc24_valid_last <= 0; 94 | end 95 | end 96 | endcase 97 | end 98 | end 99 | 100 | crc24_core # ( 101 | .CRC_STATE_BIT_WIDTH(CRC_STATE_BIT_WIDTH) 102 | ) crc24_core_i ( 103 | .clk(clk), 104 | .rst(rst), 105 | 106 | .crc_state_init_bit(crc_state_init_bit), 107 | .crc_state_init_bit_load(crc_state_init_bit_load), 108 | .data_in(info_bit), 109 | .data_in_valid(info_bit_valid_internal), 110 | 111 | .lfsr(lfsr) 112 | ); 113 | 114 | endmodule 115 | 116 | -------------------------------------------------------------------------------- /verilog/crc24_core.v: -------------------------------------------------------------------------------- 1 | // Author: Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | // Core_v5.3 figure3.4 on page 2734 6 | 7 | `timescale 1ns / 1ps 8 | module crc24_core # 9 | ( 10 | parameter CRC_STATE_BIT_WIDTH = 24 11 | ) ( 12 | input wire clk, 13 | input wire rst, 14 | 15 | input wire [(CRC_STATE_BIT_WIDTH-1) : 0] crc_state_init_bit, // load into lfsr (linear feedback shift register) upon crc_state_init_bit_load==1 16 | input wire crc_state_init_bit_load, 17 | input wire data_in, 18 | input wire data_in_valid, 19 | output reg [(CRC_STATE_BIT_WIDTH-1) : 0] lfsr 20 | ); 21 | 22 | wire [(CRC_STATE_BIT_WIDTH-1) : 0] crc_state_init_bit_switch; 23 | wire new_bit; 24 | 25 | assign crc_state_init_bit_switch[7:0] = crc_state_init_bit[(16+7):(16+0)]; 26 | assign crc_state_init_bit_switch[(8+7):(8+0)] = crc_state_init_bit[(8+7):(8+0)]; 27 | assign crc_state_init_bit_switch[(16+7):(16+0)] = crc_state_init_bit[7:0]; 28 | 29 | assign new_bit = lfsr[23]^data_in; 30 | 31 | always @ (posedge clk) begin 32 | if (rst) begin 33 | // lfsr <= 0; 34 | lfsr <= crc_state_init_bit_switch; 35 | end else begin 36 | if (crc_state_init_bit_load) begin 37 | lfsr <= crc_state_init_bit_switch; 38 | end else begin 39 | if (data_in_valid) begin 40 | // $display("%h %d %d", lfsr, data_in, new_bit); 41 | lfsr[0] <= new_bit; 42 | lfsr[1] <= lfsr[0]^new_bit; 43 | lfsr[2] <= lfsr[1]; 44 | lfsr[3] <= lfsr[2]^new_bit; 45 | lfsr[4] <= lfsr[3]^new_bit; 46 | lfsr[5] <= lfsr[4]; 47 | lfsr[6] <= lfsr[5]^new_bit; 48 | lfsr[7] <= lfsr[6]; 49 | lfsr[8] <= lfsr[7]; 50 | lfsr[9] <= lfsr[8]^new_bit; 51 | lfsr[10] <= lfsr[9]^new_bit; 52 | lfsr[23:11] <= lfsr[22:10]; 53 | end 54 | end 55 | end 56 | end 57 | 58 | endmodule 59 | 60 | -------------------------------------------------------------------------------- /verilog/crc24_tb.v: -------------------------------------------------------------------------------- 1 | // Author: Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | // To generate test vector and result reference, in python directory run: 6 | // python3 test_vector_for_btle_verilog.py 7 | // (arguments can be added: example_idx snr ppm_value) 8 | // Run verilog simulation: 9 | // iverilog -o crc24_tb crc24_tb.v crc24.v crc24_core.v 10 | // vvp crc24_tb 11 | // Check verilog outputs to see whether test pass. 12 | 13 | `timescale 1ns / 1ps 14 | module crc24_tb # 15 | ( 16 | parameter CRC_STATE_BIT_WIDTH = 24 17 | ) ( 18 | ); 19 | 20 | reg clk; 21 | reg rst; 22 | 23 | reg [64*8:0] BTLE_CONFIG_FILENAME = "btle_config.txt"; 24 | reg [64*8:0] TEST_INPUT_FILENAME = "btle_tx_crc24_test_input.txt"; 25 | reg [64*8:0] TEST_OUTPUT_REF_FILENAME = "btle_tx_crc24_test_output_ref.txt"; 26 | reg [64*8:0] TEST_OUTPUT_FILENAME = "btle_tx_crc24_test_output.txt"; 27 | 28 | reg [31:0] btle_config_mem [0:31]; 29 | reg [(CRC_STATE_BIT_WIDTH-1) : 0] CRC_STATE_INIT_BIT; 30 | 31 | reg [0:0] crc24_test_input_mem [0:4095]; 32 | reg [0:0] crc24_test_output_mem [0:4095]; 33 | reg [0:0] crc24_test_output_ref_mem [0:4095]; 34 | 35 | integer NUM_BIT_INPUT; 36 | integer crc24_test_input_fd; 37 | integer NUM_BIT_OUTPUT; 38 | integer crc24_test_output_ref_fd; 39 | integer crc24_test_output_fd; 40 | integer NUM_ERROR; 41 | integer i; 42 | integer tmp; 43 | initial begin 44 | $dumpfile("crc24_tb.vcd"); 45 | $dumpvars; 46 | $readmemh(BTLE_CONFIG_FILENAME, btle_config_mem); 47 | CRC_STATE_INIT_BIT = btle_config_mem[2]; 48 | $display("CRC_STATE_INIT_BIT %06x", CRC_STATE_INIT_BIT); 49 | 50 | // read test input 51 | $display("Reading input from %s", TEST_INPUT_FILENAME); 52 | NUM_BIT_INPUT = 0; 53 | crc24_test_input_fd = $fopen(TEST_INPUT_FILENAME, "r"); 54 | tmp = $fscanf(crc24_test_input_fd, "%d", crc24_test_input_mem[NUM_BIT_INPUT]); 55 | while(tmp == 1) begin 56 | NUM_BIT_INPUT = NUM_BIT_INPUT + 1; 57 | tmp = $fscanf(crc24_test_input_fd, "%d", crc24_test_input_mem[NUM_BIT_INPUT]); 58 | end 59 | $fclose(crc24_test_input_fd); 60 | $display("%d read finish for test input.", NUM_BIT_INPUT); 61 | 62 | // read test output reference 63 | $display("Reading output ref from %s", TEST_OUTPUT_REF_FILENAME); 64 | NUM_BIT_OUTPUT = 0; 65 | crc24_test_output_ref_fd = $fopen(TEST_OUTPUT_REF_FILENAME, "r"); 66 | tmp = $fscanf(crc24_test_output_ref_fd, "%d", crc24_test_output_ref_mem[NUM_BIT_OUTPUT]); 67 | while(tmp == 1) begin 68 | NUM_BIT_OUTPUT = NUM_BIT_OUTPUT + 1; 69 | tmp = $fscanf(crc24_test_output_ref_fd, "%d", crc24_test_output_ref_mem[NUM_BIT_OUTPUT]); 70 | end 71 | $fclose(crc24_test_output_ref_fd); 72 | $display("%d read finish for test output ref.", NUM_BIT_OUTPUT); 73 | 74 | clk = 0; 75 | rst = 0; 76 | 77 | #200 rst = 1; 78 | 79 | #200 rst = 0; 80 | end 81 | 82 | always begin 83 | #((1000.0/16.0)/2.0) clk = !clk; //16MHz 84 | end 85 | 86 | reg [(CRC_STATE_BIT_WIDTH-1) : 0] crc_state_init_bit; 87 | reg crc_state_init_bit_load; 88 | reg info_bit; 89 | reg info_bit_valid; 90 | reg info_bit_valid_last; 91 | 92 | wire info_bit_after_crc24; 93 | wire info_bit_after_crc24_valid; 94 | wire info_bit_after_crc24_valid_last; 95 | 96 | // test process 97 | reg [31:0] clk_count; 98 | reg [31:0] info_bit_count; 99 | reg [31:0] bit_out_count; 100 | reg bit_out_finish; 101 | always @ (posedge clk) begin 102 | if (rst) begin 103 | crc_state_init_bit <= 0; 104 | crc_state_init_bit_load <= 0; 105 | info_bit <= 0; 106 | info_bit_valid <= 0; 107 | info_bit_valid_last <= 0; 108 | 109 | clk_count <= 1; 110 | info_bit_count <= 0; 111 | bit_out_count <= 0; 112 | bit_out_finish <= 0; 113 | end else begin 114 | crc_state_init_bit <= CRC_STATE_INIT_BIT; 115 | clk_count <= clk_count + 1; 116 | if (clk_count == 3) begin 117 | crc_state_init_bit_load <= 1; 118 | // $display("%h", crc_state_init_bit); 119 | end else begin 120 | crc_state_init_bit_load <= 0; 121 | end 122 | 123 | if (clk_count[3:0] == 0) begin // speed 1M 124 | if (info_bit_count < NUM_BIT_INPUT) begin 125 | info_bit <= crc24_test_input_mem[info_bit_count]; 126 | info_bit_valid <= 1; 127 | if (info_bit_count == (NUM_BIT_INPUT-1)) begin 128 | info_bit_valid_last <= 1; 129 | end 130 | // $display("%h", crc24_test_input_mem[info_bit_count]); 131 | end 132 | info_bit_count <= info_bit_count + 1; 133 | end else begin 134 | info_bit_valid <= 0; 135 | info_bit_valid_last <= 0; 136 | end 137 | 138 | if (info_bit_count == (NUM_BIT_INPUT+30)) begin 139 | $display("%d input", NUM_BIT_INPUT); 140 | $display("%d output", bit_out_count); 141 | $display("Save output to %s", TEST_OUTPUT_FILENAME); 142 | // $writememh(TEST_OUTPUT_FILENAME, crc24_test_output_mem, 0, bit_out_count-1); 143 | crc24_test_output_fd = $fopen(TEST_OUTPUT_FILENAME, "w"); 144 | for (i=0; i 0) begin 159 | $display("%d error found!", NUM_ERROR); 160 | $display("Please check %s VS %s", TEST_OUTPUT_FILENAME, TEST_OUTPUT_REF_FILENAME); 161 | end else begin 162 | $display("%d error found! Test PASS.", NUM_ERROR); 163 | end 164 | $finish; 165 | end 166 | 167 | // record the result 168 | if (info_bit_after_crc24_valid) begin 169 | crc24_test_output_mem[bit_out_count] <= info_bit_after_crc24; 170 | if (info_bit_after_crc24_valid_last) begin 171 | bit_out_finish <= 1; 172 | end 173 | if (bit_out_finish == 0) begin 174 | bit_out_count <= bit_out_count + 1; 175 | end 176 | end 177 | end 178 | end 179 | 180 | crc24 # ( 181 | .CRC_STATE_BIT_WIDTH(CRC_STATE_BIT_WIDTH) 182 | ) crc24_i ( 183 | .clk(clk), 184 | .rst(rst), 185 | 186 | .crc_state_init_bit(crc_state_init_bit), 187 | .crc_state_init_bit_load(crc_state_init_bit_load), 188 | .info_bit(info_bit), 189 | .info_bit_valid(info_bit_valid), 190 | .info_bit_valid_last(info_bit_valid_last), 191 | .info_bit_after_crc24(info_bit_after_crc24), 192 | .info_bit_after_crc24_valid(info_bit_after_crc24_valid), 193 | .info_bit_after_crc24_valid_last(info_bit_after_crc24_valid_last) 194 | ); 195 | 196 | endmodule 197 | 198 | -------------------------------------------------------------------------------- /verilog/dpram.v: -------------------------------------------------------------------------------- 1 | // Author: Kenneth Wilke , Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: ISC License 4 | 5 | // Dual-ported parameterized RAM module 6 | // Based on https://github.com/KennethWilke/sv-dpram/blob/master/dpram.sv 7 | 8 | // ISC License 9 | 10 | // Copyright (c) 2023, Kenneth Wilke 11 | // Permission to use, copy, modify, and/or distribute this software for any 12 | // purpose with or without fee is hereby granted, provided that the above 13 | // copyright notice and this permission notice appear in all copies. 14 | 15 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 16 | // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 17 | // AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 18 | // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 19 | // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 20 | // OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21 | // PERFORMANCE OF THIS SOFTWARE. 22 | 23 | `timescale 1ns / 1ps 24 | module dpram # 25 | ( 26 | parameter DATA_WIDTH = 8, 27 | parameter ADDRESS_WIDTH = 11 28 | ) ( 29 | input wire clk, 30 | input wire rst, 31 | 32 | input wire [ADDRESS_WIDTH-1:0] write_address, 33 | input wire [DATA_WIDTH-1:0] write_data, 34 | input wire write_enable, 35 | 36 | input wire [ADDRESS_WIDTH-1:0] read_address, 37 | output wire [DATA_WIDTH-1:0] read_data 38 | ); 39 | 40 | reg [DATA_WIDTH-1:0] memory [0:(1< 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | // Core_v5.3 section 3.1on page 2640 6 | // BT = 0.5 7 | 8 | `timescale 1ns / 1ps 9 | module gauss_filter # 10 | ( 11 | parameter GAUSS_FILTER_BIT_WIDTH = 16, 12 | parameter NUM_TAP_GAUSS_FILTER = 17 13 | ) ( 14 | input wire clk, 15 | input wire rst, 16 | 17 | input wire [3:0] tap_index, // only need to set 0~8, 9~16 will be mirror of 0~7 18 | input wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tap_value, 19 | 20 | input wire bit_upsample, 21 | input wire bit_upsample_valid, 22 | input wire bit_upsample_valid_last, 23 | 24 | output reg signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] bit_upsample_gauss_filter, 25 | output reg bit_upsample_gauss_filter_valid, 26 | output reg bit_upsample_gauss_filter_valid_last 27 | ); 28 | 29 | reg signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] gauss_filter_tap0; 30 | reg signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] gauss_filter_tap1; 31 | reg signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] gauss_filter_tap2; 32 | reg signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] gauss_filter_tap3; 33 | reg signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] gauss_filter_tap4; 34 | reg signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] gauss_filter_tap5; 35 | reg signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] gauss_filter_tap6; 36 | reg signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] gauss_filter_tap7; 37 | reg signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] gauss_filter_tap8; 38 | 39 | reg [(NUM_TAP_GAUSS_FILTER-2) : 0] bit_upsample_store; 40 | 41 | wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tap0_mult; 42 | wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tap1_mult; 43 | wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tap2_mult; 44 | wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tap3_mult; 45 | wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tap4_mult; 46 | wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tap5_mult; 47 | wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tap6_mult; 48 | wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tap7_mult; 49 | wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tap8_mult; 50 | wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tap9_mult; 51 | wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tap10_mult; 52 | wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tap11_mult; 53 | wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tap12_mult; 54 | wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tap13_mult; 55 | wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tap14_mult; 56 | wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tap15_mult; 57 | wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tap16_mult; 58 | 59 | assign tap0_mult = (bit_upsample ? gauss_filter_tap0:(-gauss_filter_tap0)); 60 | assign tap1_mult = (bit_upsample_store[0]? gauss_filter_tap1:(-gauss_filter_tap1)); 61 | assign tap2_mult = (bit_upsample_store[1]? gauss_filter_tap2:(-gauss_filter_tap2)); 62 | assign tap3_mult = (bit_upsample_store[2]? gauss_filter_tap3:(-gauss_filter_tap3)); 63 | assign tap4_mult = (bit_upsample_store[3]? gauss_filter_tap4:(-gauss_filter_tap4)); 64 | assign tap5_mult = (bit_upsample_store[4]? gauss_filter_tap5:(-gauss_filter_tap5)); 65 | assign tap6_mult = (bit_upsample_store[5]? gauss_filter_tap6:(-gauss_filter_tap6)); 66 | assign tap7_mult = (bit_upsample_store[6]? gauss_filter_tap7:(-gauss_filter_tap7)); 67 | assign tap8_mult = (bit_upsample_store[7]? gauss_filter_tap8:(-gauss_filter_tap8)); 68 | assign tap9_mult = (bit_upsample_store[8]? gauss_filter_tap7:(-gauss_filter_tap7)); 69 | assign tap10_mult = (bit_upsample_store[9]? gauss_filter_tap6:(-gauss_filter_tap6)); 70 | assign tap11_mult = (bit_upsample_store[10]?gauss_filter_tap5:(-gauss_filter_tap5)); 71 | assign tap12_mult = (bit_upsample_store[11]?gauss_filter_tap4:(-gauss_filter_tap4)); 72 | assign tap13_mult = (bit_upsample_store[12]?gauss_filter_tap3:(-gauss_filter_tap3)); 73 | assign tap14_mult = (bit_upsample_store[13]?gauss_filter_tap2:(-gauss_filter_tap2)); 74 | assign tap15_mult = (bit_upsample_store[14]?gauss_filter_tap1:(-gauss_filter_tap1)); 75 | assign tap16_mult = (bit_upsample_store[15]?gauss_filter_tap0:(-gauss_filter_tap0)); 76 | 77 | // Populate input tap index and value to internal taps 78 | always @ (posedge clk) begin 79 | if (rst) begin 80 | gauss_filter_tap0 <= 0; 81 | gauss_filter_tap1 <= 0; 82 | gauss_filter_tap2 <= 0; 83 | gauss_filter_tap3 <= 0; 84 | gauss_filter_tap4 <= 0; 85 | gauss_filter_tap5 <= 0; 86 | gauss_filter_tap6 <= 0; 87 | gauss_filter_tap7 <= 0; 88 | gauss_filter_tap8 <= 0; 89 | end else begin 90 | case(tap_index) 91 | 0: begin gauss_filter_tap0 <= tap_value; end 92 | 1: begin gauss_filter_tap1 <= tap_value; end 93 | 2: begin gauss_filter_tap2 <= tap_value; end 94 | 3: begin gauss_filter_tap3 <= tap_value; end 95 | 4: begin gauss_filter_tap4 <= tap_value; end 96 | 5: begin gauss_filter_tap5 <= tap_value; end 97 | 6: begin gauss_filter_tap6 <= tap_value; end 98 | 7: begin gauss_filter_tap7 <= tap_value; end 99 | 8: begin gauss_filter_tap8 <= tap_value; end 100 | endcase 101 | end 102 | end 103 | 104 | 105 | always @ (posedge clk) begin 106 | if (rst) begin 107 | bit_upsample_gauss_filter <= 0; 108 | bit_upsample_gauss_filter_valid <= 0; 109 | bit_upsample_gauss_filter_valid_last <= 0; 110 | bit_upsample_store <= 0; 111 | end else begin 112 | bit_upsample_gauss_filter_valid <= bit_upsample_valid; 113 | bit_upsample_gauss_filter_valid_last <= bit_upsample_valid_last; 114 | if (bit_upsample_valid) begin 115 | bit_upsample_store[(NUM_TAP_GAUSS_FILTER-2) : 1] <= bit_upsample_store[(NUM_TAP_GAUSS_FILTER-3) : 0]; 116 | bit_upsample_store[0] <= bit_upsample; 117 | 118 | bit_upsample_gauss_filter <= (tap0_mult+tap1_mult+tap2_mult+tap3_mult+tap4_mult+tap5_mult+tap6_mult+tap7_mult+tap8_mult+tap9_mult+tap10_mult+tap11_mult+tap12_mult+tap13_mult+tap14_mult+tap15_mult+tap16_mult); 119 | end 120 | end 121 | end 122 | 123 | endmodule 124 | -------------------------------------------------------------------------------- /verilog/gauss_filter_tb.v: -------------------------------------------------------------------------------- 1 | // Author: Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | // To generate test vector and result reference, in python directory run: 6 | // python3 test_vector_for_btle_verilog.py 7 | // (arguments can be added: example_idx snr ppm_value) 8 | // Run verilog simulation: 9 | // iverilog -o gauss_filter_tb gauss_filter_tb.v gauss_filter.v 10 | // vvp gauss_filter_tb 11 | // Check verilog outputs to see whether test pass. 12 | 13 | `timescale 1ns / 1ps 14 | module gauss_filter_tb # 15 | ( 16 | parameter GAUSS_FILTER_BIT_WIDTH = 16, 17 | parameter NUM_TAP_GAUSS_FILTER = 17 18 | // parameter NUM_BIT_INPUT = 3008 19 | ) ( 20 | ); 21 | 22 | reg clk; 23 | reg rst; 24 | 25 | reg [64*8:0] GAUSS_FILTER_TAP_FILENAME = "gauss_filter_tap.txt"; 26 | reg [64*8:0] TEST_INPUT_FILENAME = "btle_tx_gauss_filter_test_input.txt"; 27 | reg [64*8:0] TEST_OUTPUT_REF_FILENAME = "btle_tx_gauss_filter_test_output_ref.txt"; 28 | reg [64*8:0] TEST_OUTPUT_FILENAME = "btle_tx_gauss_filter_test_output.txt"; 29 | 30 | reg signed [(GAUSS_FILTER_BIT_WIDTH-1):0] gauss_filter_tap_mem [0:63]; 31 | reg [0:0] gauss_filter_test_input_mem [0:4095]; 32 | reg signed [(GAUSS_FILTER_BIT_WIDTH-1):0] gauss_filter_test_output_mem [0:4095]; 33 | reg signed [(GAUSS_FILTER_BIT_WIDTH-1):0] gauss_filter_test_output_ref_mem [0:4095]; 34 | 35 | integer NUM_BIT_INPUT; 36 | integer NUM_SAMPLE_OUTPUT; 37 | integer NUM_ERROR; 38 | 39 | integer gauss_filter_tap_fd; 40 | integer gauss_filter_test_input_fd; 41 | integer gauss_filter_test_output_fd; 42 | integer gauss_filter_test_output_ref_fd; 43 | integer i; 44 | integer tmp; 45 | 46 | initial begin 47 | $dumpfile("gauss_filter_tb.vcd"); 48 | $dumpvars; 49 | 50 | // read filter tap 51 | $display("Reading from %s", GAUSS_FILTER_TAP_FILENAME); 52 | gauss_filter_tap_fd = $fopen(GAUSS_FILTER_TAP_FILENAME, "r"); 53 | for (i=0; i<((NUM_TAP_GAUSS_FILTER+1)/2); i=i+1) begin 54 | tmp = $fscanf(gauss_filter_tap_fd, "%d", gauss_filter_tap_mem[i]); 55 | end 56 | $fclose(gauss_filter_tap_fd); 57 | 58 | // read test input 59 | $display("Reading input from %s", TEST_INPUT_FILENAME); 60 | NUM_BIT_INPUT = 0; 61 | gauss_filter_test_input_fd = $fopen(TEST_INPUT_FILENAME, "r"); 62 | tmp = $fscanf(gauss_filter_test_input_fd, "%d", gauss_filter_test_input_mem[NUM_BIT_INPUT]); 63 | while(tmp == 1) begin 64 | NUM_BIT_INPUT = NUM_BIT_INPUT + 1; 65 | tmp = $fscanf(gauss_filter_test_input_fd, "%d", gauss_filter_test_input_mem[NUM_BIT_INPUT]); 66 | end 67 | $fclose(gauss_filter_test_input_fd); 68 | $display("%d read finish for test input.", NUM_BIT_INPUT); 69 | 70 | // read test output reference 71 | $display("Reading output ref from %s", TEST_OUTPUT_REF_FILENAME); 72 | NUM_SAMPLE_OUTPUT = 0; 73 | gauss_filter_test_output_ref_fd = $fopen(TEST_OUTPUT_REF_FILENAME, "r"); 74 | tmp = $fscanf(gauss_filter_test_output_ref_fd, "%d", gauss_filter_test_output_ref_mem[NUM_SAMPLE_OUTPUT]); 75 | while(tmp == 1) begin 76 | NUM_SAMPLE_OUTPUT = NUM_SAMPLE_OUTPUT + 1; 77 | tmp = $fscanf(gauss_filter_test_output_ref_fd, "%d", gauss_filter_test_output_ref_mem[NUM_SAMPLE_OUTPUT]); 78 | end 79 | $fclose(gauss_filter_test_output_ref_fd); 80 | $display("%d read finish for test output ref.", NUM_SAMPLE_OUTPUT); 81 | 82 | clk = 0; 83 | rst = 0; 84 | 85 | #200 rst = 1; 86 | 87 | #200 rst = 0; 88 | end 89 | 90 | always begin 91 | #((1000.0/16.0)/2.0) clk = !clk; //16MHz 92 | end 93 | 94 | reg [3:0] tap_index; // only need to set 0~8, 9~16 will be mirror of 0~7 95 | reg signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] tap_value; 96 | 97 | reg bit_upsample; 98 | reg bit_upsample_valid; 99 | 100 | wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] bit_upsample_gauss_filter; 101 | wire bit_upsample_gauss_filter_valid; 102 | 103 | // test process 104 | reg [31:0] clk_count; 105 | reg [31:0] bit_upsample_count; 106 | reg [31:0] bit_upsample_gauss_filter_count; 107 | always @ (posedge clk) begin 108 | if (rst) begin 109 | tap_index <= 0; 110 | tap_value <= 0; 111 | 112 | bit_upsample <= 0; 113 | bit_upsample_valid <= 0; 114 | 115 | clk_count <= 0; 116 | bit_upsample_count <= 0; 117 | bit_upsample_gauss_filter_count <= 0; 118 | end else begin 119 | clk_count <= clk_count + 1; 120 | 121 | // Initialize the gauss filter taps 122 | if (clk_count < 9) begin 123 | tap_index <= clk_count; 124 | tap_value <= gauss_filter_tap_mem[clk_count]; 125 | end else if (clk_count == 9) begin 126 | $display("gauss filter taps initialized."); 127 | end else begin 128 | 129 | if (clk_count[0] == 0) begin // speed 8M 130 | if (bit_upsample_count < NUM_BIT_INPUT) begin 131 | bit_upsample <= gauss_filter_test_input_mem[bit_upsample_count]; 132 | bit_upsample_valid <= 1; 133 | // $display("%h", gauss_filter_test_input_mem[bit_upsample_count]); 134 | end 135 | bit_upsample_count <= bit_upsample_count + 1; 136 | end else begin 137 | bit_upsample_valid <= 0; 138 | end 139 | 140 | if (bit_upsample_count == (NUM_BIT_INPUT+30)) begin 141 | $display("%d input", NUM_BIT_INPUT); 142 | $display("%d output", bit_upsample_gauss_filter_count); 143 | $display("Save output to %s", TEST_OUTPUT_FILENAME); 144 | 145 | gauss_filter_test_output_fd = $fopen(TEST_OUTPUT_FILENAME, "w"); 146 | for (i=0; i 0) begin 162 | $display("%d error found!", NUM_ERROR); 163 | $display("Please check %s VS %s", TEST_OUTPUT_FILENAME, TEST_OUTPUT_REF_FILENAME); 164 | end else begin 165 | $display("%d error found! Test PASS.", NUM_ERROR); 166 | end 167 | $finish; 168 | end 169 | 170 | // record the result 171 | if (bit_upsample_gauss_filter_valid) begin 172 | gauss_filter_test_output_mem[bit_upsample_gauss_filter_count] = bit_upsample_gauss_filter; 173 | bit_upsample_gauss_filter_count <= bit_upsample_gauss_filter_count + 1; 174 | end 175 | 176 | end 177 | end 178 | end 179 | 180 | gauss_filter # ( 181 | .GAUSS_FILTER_BIT_WIDTH(GAUSS_FILTER_BIT_WIDTH), 182 | .NUM_TAP_GAUSS_FILTER(NUM_TAP_GAUSS_FILTER) 183 | ) gauss_filter_i ( 184 | .clk(clk), 185 | .rst(rst), 186 | 187 | .tap_index(tap_index), 188 | .tap_value(tap_value), 189 | 190 | .bit_upsample(bit_upsample), 191 | .bit_upsample_valid(bit_upsample_valid), 192 | .bit_upsample_valid_last(), 193 | .bit_upsample_gauss_filter(bit_upsample_gauss_filter), 194 | .bit_upsample_gauss_filter_valid(bit_upsample_gauss_filter_valid), 195 | .bit_upsample_gauss_filter_valid_last() 196 | ); 197 | 198 | endmodule 199 | 200 | -------------------------------------------------------------------------------- /verilog/gfsk_demodulation.v: -------------------------------------------------------------------------------- 1 | // Author: Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | `timescale 1ns / 1ps 6 | module gfsk_demodulation # 7 | ( 8 | parameter GFSK_DEMODULATION_BIT_WIDTH = 16 9 | ) ( 10 | input wire clk, 11 | input wire rst, 12 | 13 | input wire signed [(GFSK_DEMODULATION_BIT_WIDTH-1) : 0] i, 14 | input wire signed [(GFSK_DEMODULATION_BIT_WIDTH-1) : 0] q, 15 | input wire iq_valid, 16 | 17 | output reg signed [(2*GFSK_DEMODULATION_BIT_WIDTH-1) : 0] signal_for_decision, 18 | output wire signal_for_decision_valid, 19 | 20 | output reg phy_bit, 21 | output wire bit_valid 22 | ); 23 | 24 | reg signed [(2*GFSK_DEMODULATION_BIT_WIDTH-1) : 0] i0; 25 | reg signed [(2*GFSK_DEMODULATION_BIT_WIDTH-1) : 0] i1; 26 | reg signed [(2*GFSK_DEMODULATION_BIT_WIDTH-1) : 0] q0; 27 | reg signed [(2*GFSK_DEMODULATION_BIT_WIDTH-1) : 0] q1; 28 | 29 | reg iq_valid_delay1; 30 | reg iq_valid_delay2; 31 | reg iq_valid_delay3; 32 | 33 | assign signal_for_decision_valid = iq_valid_delay2; 34 | assign bit_valid = iq_valid_delay3; 35 | 36 | always @ (posedge clk) begin 37 | if (rst) begin 38 | i0 <= 0; 39 | i1 <= 0; 40 | q0 <= 0; 41 | q1 <= 0; 42 | 43 | signal_for_decision <= 0; 44 | phy_bit <= 0; 45 | 46 | iq_valid_delay1 <= 0; 47 | iq_valid_delay2 <= 0; 48 | iq_valid_delay3 <= 0; 49 | end else begin 50 | iq_valid_delay1 <= iq_valid; 51 | iq_valid_delay2 <= iq_valid_delay1; 52 | iq_valid_delay3 <= iq_valid_delay2; 53 | 54 | if (iq_valid) begin 55 | i1 <= {{GFSK_DEMODULATION_BIT_WIDTH{i[GFSK_DEMODULATION_BIT_WIDTH-1]}}, i}; 56 | i0 <= i1; 57 | q1 <= {{GFSK_DEMODULATION_BIT_WIDTH{q[GFSK_DEMODULATION_BIT_WIDTH-1]}}, q}; 58 | q0 <= q1; 59 | end 60 | 61 | signal_for_decision <= i0*q1 - i1*q0; 62 | phy_bit <= (signal_for_decision > 0); 63 | 64 | end 65 | end 66 | 67 | endmodule 68 | -------------------------------------------------------------------------------- /verilog/gfsk_demodulation_tb.v: -------------------------------------------------------------------------------- 1 | // Author: Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | // To generate test vector and result reference, in python directory run: 6 | // python3 test_vector_for_btle_verilog.py 7 | // (arguments can be added: example_idx snr ppm_value) 8 | // Run verilog simulation: 9 | // iverilog -o gfsk_demodulation_tb gfsk_demodulation_tb.v gfsk_demodulation.v 10 | // vvp gfsk_demodulation_tb 11 | // Check verilog outputs to see whether test pass. 12 | 13 | `timescale 1ns / 1ps 14 | module gfsk_demodulation_tb # 15 | ( 16 | parameter GFSK_DEMODULATION_BIT_WIDTH = 16 17 | ) ( 18 | ); 19 | 20 | reg clk; 21 | reg rst; 22 | 23 | reg [72*8:0] TEST_INPUT_I_FILENAME = "btle_rx_gfsk_demodulation_test_input_i.txt"; 24 | reg [72*8:0] TEST_INPUT_Q_FILENAME = "btle_rx_gfsk_demodulation_test_input_q.txt"; 25 | reg [72*8:0] TEST_OUTPUT_SIGNAL_FOR_DECISION_REF_FILENAME = "btle_rx_gfsk_demodulation_test_output_signal_for_decision_ref.txt"; 26 | reg [72*8:0] TEST_OUTPUT_BIT_REF_FILENAME = "btle_rx_gfsk_demodulation_test_output_bit_ref.txt"; 27 | reg [72*8:0] TEST_OUTPUT_SIGNAL_FOR_DECISION_FILENAME = "btle_rx_gfsk_demodulation_test_output_signal_for_decision.txt"; 28 | reg [72*8:0] TEST_OUTPUT_BIT_FILENAME = "btle_rx_gfsk_demodulation_test_output_bit.txt"; 29 | 30 | reg signed [(GFSK_DEMODULATION_BIT_WIDTH-1):0] gfsk_demodulation_test_input_i_mem [0:4095]; 31 | reg signed [(GFSK_DEMODULATION_BIT_WIDTH-1):0] gfsk_demodulation_test_input_q_mem [0:4095]; 32 | reg [0:0] gfsk_demodulation_test_output_bit_mem [0:4095]; 33 | reg signed [(2*GFSK_DEMODULATION_BIT_WIDTH-1):0] gfsk_demodulation_test_output_signal_for_decision_mem [0:4095]; 34 | reg [0:0] gfsk_demodulation_test_output_bit_ref_mem [0:4095]; 35 | reg signed [(2*GFSK_DEMODULATION_BIT_WIDTH-1):0] gfsk_demodulation_test_output_signal_for_decision_ref_mem [0:4095]; 36 | 37 | integer gfsk_demodulation_test_input_i_fd; 38 | integer gfsk_demodulation_test_input_q_fd; 39 | integer gfsk_demodulation_test_output_bit_fd; 40 | integer gfsk_demodulation_test_output_signal_for_decision_fd; 41 | integer gfsk_demodulation_test_output_bit_ref_fd; 42 | integer gfsk_demodulation_test_output_signal_for_decision_ref_fd; 43 | integer NUM_SAMPLE_INPUT; 44 | integer NUM_BIT_OUTPUT; 45 | integer NUM_ERROR; 46 | integer tmp; 47 | integer i, j; 48 | 49 | initial begin 50 | $dumpfile("gfsk_demodulation_tb.vcd"); 51 | $dumpvars; 52 | 53 | // read test input 54 | $display("Reading input I from %s", TEST_INPUT_I_FILENAME); 55 | NUM_SAMPLE_INPUT = 0; 56 | gfsk_demodulation_test_input_i_fd = $fopen(TEST_INPUT_I_FILENAME, "r"); 57 | tmp = $fscanf(gfsk_demodulation_test_input_i_fd, "%d", gfsk_demodulation_test_input_i_mem[NUM_SAMPLE_INPUT]); 58 | while(tmp == 1) begin 59 | NUM_SAMPLE_INPUT = NUM_SAMPLE_INPUT + 1; 60 | tmp = $fscanf(gfsk_demodulation_test_input_i_fd, "%d", gfsk_demodulation_test_input_i_mem[NUM_SAMPLE_INPUT]); 61 | end 62 | $fclose(gfsk_demodulation_test_input_i_fd); 63 | $display("%d read finish for test input I.", NUM_SAMPLE_INPUT); 64 | 65 | $display("Reading input Q from %s", TEST_INPUT_Q_FILENAME); 66 | NUM_SAMPLE_INPUT = 0; 67 | gfsk_demodulation_test_input_q_fd = $fopen(TEST_INPUT_Q_FILENAME, "r"); 68 | tmp = $fscanf(gfsk_demodulation_test_input_q_fd, "%d", gfsk_demodulation_test_input_q_mem[NUM_SAMPLE_INPUT]); 69 | while(tmp == 1) begin 70 | NUM_SAMPLE_INPUT = NUM_SAMPLE_INPUT + 1; 71 | tmp = $fscanf(gfsk_demodulation_test_input_q_fd, "%d", gfsk_demodulation_test_input_q_mem[NUM_SAMPLE_INPUT]); 72 | end 73 | $fclose(gfsk_demodulation_test_input_q_fd); 74 | $display("%d read finish for test input Q.", NUM_SAMPLE_INPUT); 75 | 76 | // read test output reference 77 | $display("Reading output ref from %s", TEST_OUTPUT_SIGNAL_FOR_DECISION_REF_FILENAME); 78 | NUM_BIT_OUTPUT = 0; 79 | gfsk_demodulation_test_output_signal_for_decision_ref_fd = $fopen(TEST_OUTPUT_SIGNAL_FOR_DECISION_REF_FILENAME, "r"); 80 | tmp = $fscanf(gfsk_demodulation_test_output_signal_for_decision_ref_fd, "%d", gfsk_demodulation_test_output_signal_for_decision_ref_mem[NUM_BIT_OUTPUT]); 81 | while(tmp == 1) begin 82 | NUM_BIT_OUTPUT = NUM_BIT_OUTPUT + 1; 83 | tmp = $fscanf(gfsk_demodulation_test_output_signal_for_decision_ref_fd, "%d", gfsk_demodulation_test_output_signal_for_decision_ref_mem[NUM_BIT_OUTPUT]); 84 | end 85 | $fclose(gfsk_demodulation_test_output_signal_for_decision_ref_fd); 86 | $display("%d read finish from %s", NUM_BIT_OUTPUT, TEST_OUTPUT_SIGNAL_FOR_DECISION_REF_FILENAME); 87 | 88 | $display("Reading output ref from %s", TEST_OUTPUT_BIT_REF_FILENAME); 89 | NUM_BIT_OUTPUT = 0; 90 | gfsk_demodulation_test_output_bit_ref_fd = $fopen(TEST_OUTPUT_BIT_REF_FILENAME, "r"); 91 | tmp = $fscanf(gfsk_demodulation_test_output_bit_ref_fd, "%d", gfsk_demodulation_test_output_bit_ref_mem[NUM_BIT_OUTPUT]); 92 | while(tmp == 1) begin 93 | NUM_BIT_OUTPUT = NUM_BIT_OUTPUT + 1; 94 | tmp = $fscanf(gfsk_demodulation_test_output_bit_ref_fd, "%d", gfsk_demodulation_test_output_bit_ref_mem[NUM_BIT_OUTPUT]); 95 | end 96 | $fclose(gfsk_demodulation_test_output_bit_ref_fd); 97 | $display("%d read finish from %s", NUM_BIT_OUTPUT, TEST_OUTPUT_BIT_REF_FILENAME); 98 | 99 | clk = 0; 100 | rst = 0; 101 | 102 | #200 rst = 1; 103 | 104 | #200 rst = 0; 105 | end 106 | 107 | always begin 108 | #((1000.0/16.0)/2.0) clk = !clk; //16MHz 109 | end 110 | 111 | reg signed [(GFSK_DEMODULATION_BIT_WIDTH-1) : 0] i_signal; 112 | reg signed [(GFSK_DEMODULATION_BIT_WIDTH-1) : 0] q_signal; 113 | reg iq_valid; 114 | 115 | wire signed [(2*GFSK_DEMODULATION_BIT_WIDTH-1) : 0] signal_for_decision; 116 | wire signal_for_decision_valid; 117 | 118 | wire bit; 119 | wire bit_valid; 120 | 121 | // test process 122 | reg [31:0] clk_count; 123 | reg [31:0] sample_in_count; 124 | reg [31:0] bit_out_count; 125 | reg [31:0] signal_for_decision_out_count; 126 | always @ (posedge clk) begin 127 | if (rst) begin 128 | i_signal <= 0; 129 | q_signal <= 0; 130 | iq_valid <= 0; 131 | 132 | clk_count <= 1; 133 | sample_in_count <= 0; 134 | bit_out_count <= 0; 135 | signal_for_decision_out_count <= 0; 136 | end else begin 137 | clk_count <= clk_count + 1; 138 | 139 | if (clk_count[3:0] == 0) begin // speed 1M 140 | if (sample_in_count < NUM_SAMPLE_INPUT) begin 141 | i_signal <= gfsk_demodulation_test_input_i_mem[sample_in_count]; 142 | q_signal <= gfsk_demodulation_test_input_q_mem[sample_in_count]; 143 | iq_valid <= 1; 144 | end 145 | sample_in_count <= sample_in_count + 1; 146 | end else begin 147 | iq_valid <= 0; 148 | end 149 | 150 | if (sample_in_count == (NUM_SAMPLE_INPUT+30)) begin 151 | $display("%d input", NUM_SAMPLE_INPUT); 152 | $display("%d bit output", bit_out_count); 153 | $display("%d signal for decision output", signal_for_decision_out_count); 154 | 155 | $display("Save output bit to %s", TEST_OUTPUT_BIT_FILENAME); 156 | gfsk_demodulation_test_output_bit_fd = $fopen(TEST_OUTPUT_BIT_FILENAME, "w"); 157 | for (i=0; i 0) begin 179 | $display("%d error found!", NUM_ERROR); 180 | $display("Please check %s VS %s", TEST_OUTPUT_BIT_FILENAME, TEST_OUTPUT_BIT_REF_FILENAME); 181 | end else begin 182 | $display("%d error found! output bit Test PASS.", NUM_ERROR); 183 | end 184 | 185 | $display("Compare the gfsk_demodulation_test_output_signal_for_decision_mem and the gfsk_demodulation_test_output_signal_for_decision_ref_mem ..."); 186 | NUM_ERROR = 0; 187 | for (i=0; i 0) begin 193 | $display("%d error found!", NUM_ERROR); 194 | $display("Please check %s VS %s", TEST_OUTPUT_SIGNAL_FOR_DECISION_FILENAME, TEST_OUTPUT_SIGNAL_FOR_DECISION_REF_FILENAME); 195 | end else begin 196 | $display("%d error found! output signal for decision Test PASS.", NUM_ERROR); 197 | end 198 | 199 | $finish; 200 | end 201 | 202 | // record the result 203 | if (bit_valid) begin 204 | gfsk_demodulation_test_output_bit_mem[bit_out_count] <= bit; 205 | bit_out_count <= bit_out_count + 1; 206 | end 207 | 208 | if (signal_for_decision_valid) begin 209 | gfsk_demodulation_test_output_signal_for_decision_mem[signal_for_decision_out_count] <= signal_for_decision; 210 | signal_for_decision_out_count <= signal_for_decision_out_count + 1; 211 | end 212 | 213 | end 214 | end 215 | 216 | gfsk_demodulation # ( 217 | .GFSK_DEMODULATION_BIT_WIDTH(GFSK_DEMODULATION_BIT_WIDTH) 218 | ) gfsk_demodulation_i ( 219 | .clk(clk), 220 | .rst(rst), 221 | 222 | .i(i_signal), 223 | .q(q_signal), 224 | .iq_valid(iq_valid), 225 | 226 | .signal_for_decision(signal_for_decision), 227 | .signal_for_decision_valid(signal_for_decision_valid), 228 | 229 | .phy_bit(bit), 230 | .bit_valid(bit_valid) 231 | ); 232 | 233 | endmodule 234 | 235 | -------------------------------------------------------------------------------- /verilog/gfsk_modulation.v: -------------------------------------------------------------------------------- 1 | // Author: Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | `timescale 1ns / 1ps 6 | module gfsk_modulation # 7 | ( 8 | parameter SAMPLE_PER_SYMBOL = 8, 9 | parameter GAUSS_FILTER_BIT_WIDTH = 16, 10 | parameter NUM_TAP_GAUSS_FILTER = 17, 11 | parameter VCO_BIT_WIDTH = 16, 12 | parameter SIN_COS_ADDR_BIT_WIDTH = 11, 13 | parameter IQ_BIT_WIDTH = 8, 14 | parameter GAUSS_FIR_OUT_AMP_SCALE_DOWN_NUM_BIT_SHIFT = 1 15 | ) ( 16 | input wire clk, 17 | input wire rst, 18 | 19 | input wire [3:0] gauss_filter_tap_index, // only need to set 0~8, 9~16 will be mirror of 0~7 20 | input wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] gauss_filter_tap_value, 21 | 22 | input wire [(SIN_COS_ADDR_BIT_WIDTH-1) : 0] cos_table_write_address, 23 | input wire signed [(IQ_BIT_WIDTH-1) : 0] cos_table_write_data, 24 | input wire [(SIN_COS_ADDR_BIT_WIDTH-1) : 0] sin_table_write_address, 25 | input wire signed [(IQ_BIT_WIDTH-1) : 0] sin_table_write_data, 26 | 27 | input wire phy_bit, 28 | input wire bit_valid, 29 | input wire bit_valid_last, 30 | 31 | output wire signed [(IQ_BIT_WIDTH-1) : 0] cos_out, 32 | output wire signed [(IQ_BIT_WIDTH-1) : 0] sin_out, 33 | output wire sin_cos_out_valid, 34 | output wire sin_cos_out_valid_last, 35 | 36 | // for debug purpose 37 | output wire bit_upsample, 38 | output wire bit_upsample_valid, 39 | output wire bit_upsample_valid_last, 40 | 41 | output wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] bit_upsample_gauss_filter, 42 | output wire bit_upsample_gauss_filter_valid, 43 | output wire bit_upsample_gauss_filter_valid_last 44 | ); 45 | 46 | // wire bit_upsample; 47 | // wire bit_upsample_valid; 48 | // wire bit_upsample_valid_last; 49 | 50 | // wire signed [(GAUSS_FILTER_BIT_WIDTH-1) : 0] bit_upsample_gauss_filter; 51 | // wire bit_upsample_gauss_filter_valid; 52 | // wire bit_upsample_gauss_filter_valid_last; 53 | 54 | // always @ (posedge clk) begin 55 | // if (bit_upsample_gauss_filter_valid) begin 56 | // $display("%d", bit_upsample_gauss_filter); 57 | // end 58 | // end 59 | 60 | bit_repeat_upsample # ( 61 | .SAMPLE_PER_SYMBOL(SAMPLE_PER_SYMBOL) 62 | ) bit_repeat_upsample_i ( 63 | .clk(clk), 64 | .rst(rst), 65 | 66 | .phy_bit(phy_bit), 67 | .bit_valid(bit_valid), 68 | .bit_valid_last(bit_valid_last), 69 | 70 | .bit_upsample(bit_upsample), 71 | .bit_upsample_valid(bit_upsample_valid), 72 | .bit_upsample_valid_last(bit_upsample_valid_last) 73 | ); 74 | 75 | gauss_filter # ( 76 | .GAUSS_FILTER_BIT_WIDTH(GAUSS_FILTER_BIT_WIDTH), 77 | .NUM_TAP_GAUSS_FILTER(NUM_TAP_GAUSS_FILTER) 78 | ) gauss_filter_i ( 79 | .clk(clk), 80 | .rst(rst), 81 | 82 | .tap_index(gauss_filter_tap_index), 83 | .tap_value(gauss_filter_tap_value), 84 | 85 | .bit_upsample(bit_upsample), 86 | .bit_upsample_valid(bit_upsample_valid), 87 | .bit_upsample_valid_last(bit_upsample_valid_last), 88 | 89 | .bit_upsample_gauss_filter(bit_upsample_gauss_filter), 90 | .bit_upsample_gauss_filter_valid(bit_upsample_gauss_filter_valid), 91 | .bit_upsample_gauss_filter_valid_last(bit_upsample_gauss_filter_valid_last) 92 | ); 93 | 94 | vco # ( 95 | .VCO_BIT_WIDTH(VCO_BIT_WIDTH), 96 | .SIN_COS_ADDR_BIT_WIDTH(SIN_COS_ADDR_BIT_WIDTH), 97 | .IQ_BIT_WIDTH(IQ_BIT_WIDTH) 98 | ) vco_i ( 99 | .clk(clk), 100 | .rst(rst), 101 | 102 | .cos_table_write_address(cos_table_write_address), 103 | .cos_table_write_data(cos_table_write_data), 104 | .sin_table_write_address(sin_table_write_address), 105 | .sin_table_write_data(sin_table_write_data), 106 | 107 | .voltage_signal({{GAUSS_FIR_OUT_AMP_SCALE_DOWN_NUM_BIT_SHIFT{1'b1}}, bit_upsample_gauss_filter[(GAUSS_FILTER_BIT_WIDTH-1) : GAUSS_FIR_OUT_AMP_SCALE_DOWN_NUM_BIT_SHIFT]}), 108 | .voltage_signal_valid(bit_upsample_gauss_filter_valid), 109 | .voltage_signal_valid_last(bit_upsample_gauss_filter_valid_last), 110 | 111 | .cos_out(cos_out), 112 | .sin_out(sin_out), 113 | .sin_cos_out_valid(sin_cos_out_valid), 114 | .sin_cos_out_valid_last(sin_cos_out_valid_last) 115 | ); 116 | 117 | endmodule 118 | 119 | -------------------------------------------------------------------------------- /verilog/rx_clk_gen.v: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------- 2 | // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<< 3 | // -------------------------------------------------------------------- 4 | // Author: halftop 5 | // Github: https://github.com/halftop 6 | // Email: yu.zh@live.com 7 | // Description: generate uart rx sample clk = 9 x BAUD_RATE 8 | // Dependencies: 9 | // Since: 2019-06-09 16:30:57 10 | // LastEditors: halftop 11 | // LastEditTime: 2019-06-09 16:30:57 12 | // ******************************************************************** 13 | // Module Function: generate uart rx sample clk = 9 x BAUD_RATE 14 | `timescale 1ns / 1ps 15 | 16 | module rx_clk_gen 17 | #( 18 | parameter CLK_FREQUENCE = 50_000_000, //hz 19 | BAUD_RATE = 9600 //9600、19200 、38400 、57600 、115200、230400、460800、921600 20 | ) 21 | ( 22 | input clk , 23 | input rst_n , 24 | input rx_start , 25 | input rx_done , 26 | output reg sample_clk 27 | ); 28 | 29 | localparam SMP_CLK_CNT = CLK_FREQUENCE/BAUD_RATE/9 - 1, 30 | CNT_WIDTH = log2(SMP_CLK_CNT) ; 31 | 32 | reg [CNT_WIDTH-1:0] clk_count ; 33 | reg cstate; 34 | reg nstate; 35 | //FSM-1 1'b0:IDLE 1'b1:RECEIVE 36 | always @(posedge clk or negedge rst_n) begin 37 | if (!rst_n) begin 38 | cstate <= 1'b0; 39 | end else begin 40 | cstate <= nstate; 41 | end 42 | end 43 | //FSM-2 44 | always @(*) begin 45 | case (cstate) 46 | 1'b0: nstate = rx_start ? 1'b1 : 1'b0; 47 | 1'b1: nstate = rx_done ? 1'b0 : 1'b1 ; 48 | default: nstate = 1'b0; 49 | endcase 50 | end 51 | //FSM-3 FSM's output(clk_count_en) is equal to cstate 52 | 53 | //sample_clk_counter 54 | always @(posedge clk or negedge rst_n) begin 55 | if (!rst_n) 56 | clk_count <= 'd0; 57 | else if (!cstate) 58 | clk_count <= 'd0; 59 | else if (clk_count == SMP_CLK_CNT) 60 | clk_count <= 'd0; 61 | else 62 | clk_count <= clk_count + 1'b1; 63 | end 64 | //generate sample_clk = 9xBAUD_RATE 65 | always @(posedge clk or negedge rst_n) begin 66 | if (!rst_n) 67 | sample_clk <= 1'b0; 68 | else if (clk_count == 1'b1) 69 | sample_clk <= 1'b1; 70 | else 71 | sample_clk <= 1'b0; 72 | end 73 | //get the width of sample_clk_counter 74 | function integer log2(input integer v); 75 | begin 76 | log2=0; 77 | while(v>>log2) 78 | log2=log2+1; 79 | end 80 | endfunction 81 | 82 | endmodule -------------------------------------------------------------------------------- /verilog/scramble.v: -------------------------------------------------------------------------------- 1 | // Author: Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | // Core_v5.3 figure3.5 on page 2735 6 | 7 | `timescale 1ns / 1ps 8 | module scramble # 9 | ( 10 | parameter CHANNEL_NUMBER_BIT_WIDTH = 6 11 | ) ( 12 | input wire clk, 13 | input wire rst, 14 | 15 | input wire [(CHANNEL_NUMBER_BIT_WIDTH-1) : 0] channel_number, // load into lfsr (linear feedback shift register) upon channel_number_load==1 16 | input wire channel_number_load, 17 | input wire data_in, 18 | input wire data_in_valid, 19 | input wire data_in_valid_last, // if this is true together with valid, it means last bit input 20 | output wire data_out, 21 | output wire data_out_valid, 22 | output wire data_out_valid_last // indicate last bit out together with data_out_valid 23 | ); 24 | 25 | localparam [0:0] IDLE = 0, 26 | WORK_ON_INPUT = 1; 27 | 28 | reg [0:0] scramble_state; 29 | 30 | wire data_in_valid_internal; 31 | wire data_out_internal; 32 | wire data_out_valid_internal; 33 | wire scramble_start_for_input; 34 | wire scramble_start_for_output; 35 | 36 | reg data_in_delay; 37 | reg data_in_valid_delay; 38 | reg data_in_valid_last_delay; 39 | 40 | reg [8:0] data_in_count; 41 | 42 | assign scramble_start_for_input = (data_in_count>=40); 43 | assign data_in_valid_internal = (scramble_start_for_input? data_in_valid : 0); 44 | 45 | assign scramble_start_for_output = (data_in_count>=41); 46 | assign data_out = (scramble_start_for_output? data_out_internal : data_in_delay); 47 | 48 | assign data_out_valid = data_in_valid_delay; 49 | assign data_out_valid_last = data_in_valid_last_delay; 50 | 51 | scramble_core # ( 52 | .CHANNEL_NUMBER_BIT_WIDTH(CHANNEL_NUMBER_BIT_WIDTH) 53 | ) crc24_core_i ( 54 | .clk(clk), 55 | .rst(rst), 56 | 57 | .channel_number(channel_number), 58 | .channel_number_load(channel_number_load), 59 | .data_in(data_in), 60 | .data_in_valid(data_in_valid_internal), 61 | .data_out(data_out_internal), 62 | .data_out_valid(data_out_valid_internal) 63 | ); 64 | 65 | always @ (posedge clk) begin 66 | if (rst) begin 67 | data_in_delay <= 0; 68 | data_in_valid_delay <= 0; 69 | data_in_valid_last_delay <= 0; 70 | 71 | data_in_count <= 0; 72 | 73 | scramble_state <= IDLE; 74 | end else begin 75 | data_in_delay <= data_in; 76 | data_in_valid_delay <= data_in_valid; 77 | data_in_valid_last_delay <= data_in_valid_last; 78 | 79 | case(scramble_state) 80 | IDLE: begin 81 | data_in_count <= (data_in_valid ? (data_in_count+1) : data_in_count); 82 | 83 | scramble_state <= (data_in_valid ? WORK_ON_INPUT : scramble_state); 84 | end 85 | 86 | WORK_ON_INPUT: begin 87 | if (data_in_valid_last_delay) begin 88 | data_in_count <= 0; 89 | scramble_state <= IDLE; 90 | end else begin 91 | data_in_count <= (data_in_valid ? (data_in_count+1) : data_in_count); 92 | end 93 | end 94 | endcase 95 | end 96 | end 97 | 98 | endmodule 99 | -------------------------------------------------------------------------------- /verilog/scramble_core.v: -------------------------------------------------------------------------------- 1 | // Author: Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | // Core_v5.3 figure3.5 on page 2735 6 | 7 | `timescale 1ns / 1ps 8 | module scramble_core # 9 | ( 10 | parameter CHANNEL_NUMBER_BIT_WIDTH = 6 11 | ) ( 12 | input wire clk, 13 | input wire rst, 14 | 15 | input wire [(CHANNEL_NUMBER_BIT_WIDTH-1) : 0] channel_number, // load into lfsr (linear feedback shift register) upon channel_number_load==1 16 | input wire channel_number_load, 17 | input wire data_in, 18 | input wire data_in_valid, 19 | output reg data_out, 20 | output reg data_out_valid 21 | ); 22 | 23 | reg [CHANNEL_NUMBER_BIT_WIDTH : 0] lfsr; 24 | 25 | always @ (posedge clk) begin 26 | if (rst) begin 27 | data_out <= 0; 28 | data_out_valid <= 0; 29 | // lfsr <= 0; 30 | lfsr[0] <= 1; 31 | // lfsr[CHANNEL_NUMBER_BIT_WIDTH : 1] <= channel_number; 32 | lfsr[1] <= channel_number[5]; 33 | lfsr[2] <= channel_number[4]; 34 | lfsr[3] <= channel_number[3]; 35 | lfsr[4] <= channel_number[2]; 36 | lfsr[5] <= channel_number[1]; 37 | lfsr[6] <= channel_number[0]; 38 | end else begin 39 | if (channel_number_load) begin 40 | lfsr[0] <= 1; 41 | // lfsr[CHANNEL_NUMBER_BIT_WIDTH : 1] <= channel_number; 42 | lfsr[1] <= channel_number[5]; 43 | lfsr[2] <= channel_number[4]; 44 | lfsr[3] <= channel_number[3]; 45 | lfsr[4] <= channel_number[2]; 46 | lfsr[5] <= channel_number[1]; 47 | lfsr[6] <= channel_number[0]; 48 | end else begin 49 | if (data_in_valid) begin 50 | lfsr[0] <= lfsr[6]; 51 | lfsr[1] <= lfsr[0]; 52 | lfsr[2] <= lfsr[1]; 53 | lfsr[3] <= lfsr[2]; 54 | lfsr[4] <= lfsr[3]^lfsr[6]; 55 | lfsr[5] <= lfsr[4]; 56 | lfsr[6] <= lfsr[5]; 57 | 58 | data_out <= lfsr[6]^data_in; 59 | data_out_valid <= 1; 60 | end else begin 61 | data_out_valid <= 0; 62 | end 63 | end 64 | end 65 | end 66 | 67 | endmodule 68 | 69 | -------------------------------------------------------------------------------- /verilog/scramble_tb.v: -------------------------------------------------------------------------------- 1 | // Author: Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | // To generate test vector and result reference, in python directory run: 6 | // python3 test_vector_for_btle_verilog.py 7 | // (arguments can be added: example_idx snr ppm_value) 8 | // Run verilog simulation: 9 | // iverilog -o scramble_tb scramble_tb.v scramble.v scramble_core.v 10 | // vvp scramble_tb 11 | // Check verilog outputs to see whether test pass. 12 | 13 | `timescale 1ns / 1ps 14 | module scramble_tb # 15 | ( 16 | parameter CHANNEL_NUMBER_BIT_WIDTH = 6 17 | ) ( 18 | ); 19 | 20 | reg clk; 21 | reg rst; 22 | 23 | reg [64*8:0] BTLE_CONFIG_FILENAME = "btle_config.txt"; 24 | reg [64*8:0] TEST_INPUT_FILENAME = "btle_tx_scramble_test_input.txt"; 25 | reg [64*8:0] TEST_OUTPUT_REF_FILENAME = "btle_tx_scramble_test_output_ref.txt"; 26 | reg [64*8:0] TEST_OUTPUT_FILENAME = "btle_tx_scramble_test_output.txt"; 27 | 28 | reg [31:0] btle_config_mem [0:31]; 29 | reg [(CHANNEL_NUMBER_BIT_WIDTH-1) : 0] CHANNEL_NUMBER; 30 | 31 | reg [0:0] scramble_test_input_mem [0:4095]; 32 | reg [0:0] scramble_test_output_mem [0:4095]; 33 | reg [0:0] scramble_test_output_ref_mem [0:4095]; 34 | 35 | integer NUM_BIT_INPUT; 36 | integer scramble_test_input_fd; 37 | integer NUM_BIT_OUTPUT; 38 | integer scramble_test_output_ref_fd; 39 | integer scramble_test_output_fd; 40 | integer NUM_ERROR; 41 | integer i; 42 | integer tmp; 43 | 44 | initial begin 45 | $dumpfile("scramble_tb.vcd"); 46 | $dumpvars; 47 | $readmemh(BTLE_CONFIG_FILENAME, btle_config_mem); 48 | CHANNEL_NUMBER = btle_config_mem[1]; 49 | $display("CHANNEL_NUMBER %d", CHANNEL_NUMBER); 50 | 51 | // read test input 52 | $display("Reading input from %s", TEST_INPUT_FILENAME); 53 | NUM_BIT_INPUT = 0; 54 | scramble_test_input_fd = $fopen(TEST_INPUT_FILENAME, "r"); 55 | tmp = $fscanf(scramble_test_input_fd, "%d", scramble_test_input_mem[NUM_BIT_INPUT]); 56 | while(tmp == 1) begin 57 | NUM_BIT_INPUT = NUM_BIT_INPUT + 1; 58 | tmp = $fscanf(scramble_test_input_fd, "%d", scramble_test_input_mem[NUM_BIT_INPUT]); 59 | end 60 | $fclose(scramble_test_input_fd); 61 | $display("%d read finish for test input.", NUM_BIT_INPUT); 62 | 63 | // read test output reference 64 | $display("Reading output ref from %s", TEST_OUTPUT_REF_FILENAME); 65 | NUM_BIT_OUTPUT = 0; 66 | scramble_test_output_ref_fd = $fopen(TEST_OUTPUT_REF_FILENAME, "r"); 67 | tmp = $fscanf(scramble_test_output_ref_fd, "%d", scramble_test_output_ref_mem[NUM_BIT_OUTPUT]); 68 | while(tmp == 1) begin 69 | NUM_BIT_OUTPUT = NUM_BIT_OUTPUT + 1; 70 | tmp = $fscanf(scramble_test_output_ref_fd, "%d", scramble_test_output_ref_mem[NUM_BIT_OUTPUT]); 71 | end 72 | $fclose(scramble_test_output_ref_fd); 73 | $display("%d read finish for test output.", NUM_BIT_OUTPUT); 74 | 75 | clk = 0; 76 | rst = 0; 77 | 78 | #200 rst = 1; 79 | 80 | #200 rst = 0; 81 | end 82 | 83 | always begin 84 | #((1000.0/16.0)/2.0) clk = !clk; //16MHz 85 | end 86 | 87 | reg [(CHANNEL_NUMBER_BIT_WIDTH-1) : 0] channel_number; 88 | reg channel_number_load; 89 | reg data_in; 90 | reg data_in_valid; 91 | reg data_in_valid_last; 92 | 93 | wire data_out; 94 | wire data_out_valid; 95 | wire data_out_valid_last; 96 | 97 | // test process 98 | reg [31:0] clk_count; 99 | reg [31:0] info_bit_count; 100 | reg [31:0] bit_out_count; 101 | reg bit_out_finish; 102 | always @ (posedge clk) begin 103 | if (rst) begin 104 | channel_number <= 0; 105 | channel_number_load <= 0; 106 | data_in <= 0; 107 | data_in_valid <= 0; 108 | data_in_valid_last <= 0; 109 | 110 | clk_count <= 1; 111 | info_bit_count <= 0; 112 | bit_out_count <= 0; 113 | bit_out_finish <= 0; 114 | end else begin 115 | channel_number <= CHANNEL_NUMBER; 116 | clk_count <= clk_count + 1; 117 | if (clk_count == 3) begin 118 | channel_number_load <= 1; 119 | // $display("%h", channel_number); 120 | end else begin 121 | channel_number_load <= 0; 122 | end 123 | 124 | if (clk_count[3:0] == 0) begin // speed 1M 125 | if (info_bit_count < NUM_BIT_INPUT) begin 126 | data_in <= scramble_test_input_mem[info_bit_count]; 127 | data_in_valid <= 1; 128 | if (info_bit_count == (NUM_BIT_INPUT-1)) begin 129 | data_in_valid_last <= 1; 130 | end 131 | // $display("%h", scramble_test_input_mem[info_bit_count]); 132 | end 133 | info_bit_count <= info_bit_count + 1; 134 | end else begin 135 | data_in_valid <= 0; 136 | data_in_valid_last <= 0; 137 | end 138 | 139 | if (info_bit_count == (NUM_BIT_INPUT+30)) begin 140 | $display("%d input", NUM_BIT_INPUT); 141 | $display("%d output", bit_out_count); 142 | $display("Save output to %s", TEST_OUTPUT_FILENAME); 143 | // $writememh(TEST_OUTPUT_FILENAME, scramble_test_output_mem, 0, bit_out_count-1); 144 | scramble_test_output_fd = $fopen(TEST_OUTPUT_FILENAME, "w"); 145 | for (i=0; i 0) begin 160 | $display("%d error found!", NUM_ERROR); 161 | $display("Please check %s VS %s", TEST_OUTPUT_FILENAME, TEST_OUTPUT_REF_FILENAME); 162 | end else begin 163 | $display("%d error found! Test PASS.", NUM_ERROR); 164 | end 165 | $finish; 166 | end 167 | 168 | // record the result 169 | if (data_out_valid) begin 170 | scramble_test_output_mem[bit_out_count] <= data_out; 171 | if (data_out_valid_last) begin 172 | bit_out_finish <= 1; 173 | end 174 | if (bit_out_finish == 0) begin 175 | bit_out_count <= bit_out_count + 1; 176 | end 177 | end 178 | end 179 | end 180 | 181 | scramble # ( 182 | .CHANNEL_NUMBER_BIT_WIDTH(CHANNEL_NUMBER_BIT_WIDTH) 183 | ) scramble_i ( 184 | .clk(clk), 185 | .rst(rst), 186 | 187 | .channel_number(channel_number), 188 | .channel_number_load(channel_number_load), 189 | .data_in(data_in), 190 | .data_in_valid(data_in_valid), 191 | .data_in_valid_last(data_in_valid_last), 192 | .data_out(data_out), 193 | .data_out_valid(data_out_valid), 194 | .data_out_valid_last(data_out_valid_last) 195 | ); 196 | 197 | endmodule 198 | 199 | -------------------------------------------------------------------------------- /verilog/search_unique_bit_sequence.v: -------------------------------------------------------------------------------- 1 | // Author: Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | `timescale 1ns / 1ps 6 | module search_unique_bit_sequence # 7 | ( 8 | parameter LEN_UNIQUE_BIT_SEQUENCE = 32 9 | ) ( 10 | input wire clk, 11 | input wire rst, 12 | 13 | input wire phy_bit, 14 | input wire bit_valid, 15 | input wire [(LEN_UNIQUE_BIT_SEQUENCE-1) : 0] unique_bit_sequence, 16 | output wire hit_flag 17 | ); 18 | 19 | reg bit_valid_delay1; 20 | reg [(LEN_UNIQUE_BIT_SEQUENCE-1) : 0] bit_store; 21 | 22 | assign hit_flag = (bit_store == unique_bit_sequence)&bit_valid_delay1; 23 | 24 | always @ (posedge clk) begin 25 | if (rst) begin 26 | bit_store <= 0; 27 | bit_valid_delay1 <= 0; 28 | end else begin 29 | bit_valid_delay1 <= bit_valid; 30 | if (bit_valid) begin 31 | bit_store[LEN_UNIQUE_BIT_SEQUENCE-1] <= phy_bit; 32 | bit_store[(LEN_UNIQUE_BIT_SEQUENCE-2) : 0] <= bit_store[(LEN_UNIQUE_BIT_SEQUENCE-1) : 1]; 33 | end 34 | end 35 | end 36 | 37 | endmodule 38 | -------------------------------------------------------------------------------- /verilog/search_unique_bit_sequence_tb.v: -------------------------------------------------------------------------------- 1 | // Author: Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | // To generate test vector and result reference, in python directory run: 6 | // python3 test_vector_for_btle_verilog.py 7 | // (arguments can be added: example_idx snr ppm_value) 8 | // Run verilog simulation: 9 | // iverilog -o search_unique_bit_sequence_tb search_unique_bit_sequence_tb.v search_unique_bit_sequence.v 10 | // vvp search_unique_bit_sequence_tb 11 | // Check verilog outputs to see whether test pass. 12 | 13 | `timescale 1ns / 1ps 14 | module search_unique_bit_sequence_tb # 15 | ( 16 | parameter LEN_UNIQUE_BIT_SEQUENCE = 32 17 | ) ( 18 | ); 19 | 20 | reg clk; 21 | reg rst; 22 | 23 | reg [64*8:0] BTLE_CONFIG_FILENAME = "btle_config.txt"; 24 | reg [64*8:0] TEST_INPUT_FILENAME = "btle_rx_search_unique_bit_sequence_test_input.txt"; 25 | reg [64*8:0] TEST_OUTPUT_REF_FILENAME = "btle_rx_search_unique_bit_sequence_test_output_ref.txt"; 26 | 27 | reg [31:0] btle_config_mem [0:31]; 28 | reg signed [0:0] search_unique_bit_sequence_test_input_mem [0:4095]; 29 | reg signed [15:0] search_unique_bit_sequence_test_output_ref_mem [0:3]; 30 | 31 | reg [(LEN_UNIQUE_BIT_SEQUENCE-1) : 0] ACCESS_ADDRESS; 32 | 33 | integer search_unique_bit_sequence_test_input_fd; 34 | integer search_unique_bit_sequence_test_output_ref_fd; 35 | integer NUM_BIT_INPUT; 36 | integer NUM_SAMPLE_OUTPUT; 37 | integer tmp; 38 | integer i, j; 39 | 40 | initial begin 41 | $dumpfile("search_unique_bit_sequence_tb.vcd"); 42 | $dumpvars; 43 | $readmemh(BTLE_CONFIG_FILENAME, btle_config_mem); 44 | // ACCESS_ADDRESS = btle_config_mem[3]; 45 | // byte re-order 46 | ACCESS_ADDRESS[7 :0] = btle_config_mem[3][31:24]; 47 | ACCESS_ADDRESS[15:8] = btle_config_mem[3][23:16]; 48 | ACCESS_ADDRESS[23:16] = btle_config_mem[3][15:8]; 49 | ACCESS_ADDRESS[31:24] = btle_config_mem[3][7 :0]; 50 | $display("ACCESS_ADDRESS %08x", ACCESS_ADDRESS); 51 | 52 | // read test input 53 | $display("Reading input from %s", TEST_INPUT_FILENAME); 54 | NUM_BIT_INPUT = 0; 55 | search_unique_bit_sequence_test_input_fd = $fopen(TEST_INPUT_FILENAME, "r"); 56 | tmp = $fscanf(search_unique_bit_sequence_test_input_fd, "%h", search_unique_bit_sequence_test_input_mem[NUM_BIT_INPUT]); 57 | while(tmp == 1) begin 58 | NUM_BIT_INPUT = NUM_BIT_INPUT + 1; 59 | tmp = $fscanf(search_unique_bit_sequence_test_input_fd, "%h", search_unique_bit_sequence_test_input_mem[NUM_BIT_INPUT]); 60 | end 61 | $fclose(search_unique_bit_sequence_test_input_fd); 62 | $display("%d read finish from %s", NUM_BIT_INPUT, TEST_INPUT_FILENAME); 63 | 64 | // read test output reference 65 | $display("Reading output ref from %s", TEST_OUTPUT_REF_FILENAME); 66 | NUM_SAMPLE_OUTPUT = 0; 67 | search_unique_bit_sequence_test_output_ref_fd = $fopen(TEST_OUTPUT_REF_FILENAME, "r"); 68 | tmp = $fscanf(search_unique_bit_sequence_test_output_ref_fd, "%d", search_unique_bit_sequence_test_output_ref_mem[NUM_SAMPLE_OUTPUT]); 69 | while(tmp == 1) begin 70 | NUM_SAMPLE_OUTPUT = NUM_SAMPLE_OUTPUT + 1; 71 | tmp = $fscanf(search_unique_bit_sequence_test_output_ref_fd, "%d", search_unique_bit_sequence_test_output_ref_mem[NUM_SAMPLE_OUTPUT]); 72 | end 73 | $fclose(search_unique_bit_sequence_test_output_ref_fd); 74 | $display("%d read finish from %s", NUM_SAMPLE_OUTPUT, TEST_OUTPUT_REF_FILENAME); 75 | 76 | clk = 0; 77 | rst = 0; 78 | 79 | #200 rst = 1; 80 | 81 | #200 rst = 0; 82 | end 83 | 84 | always begin 85 | #((1000.0/16.0)/2.0) clk = !clk; //16MHz 86 | end 87 | 88 | reg bit; 89 | reg bit_valid; 90 | reg [(LEN_UNIQUE_BIT_SEQUENCE-1) : 0] unique_bit_sequence; 91 | 92 | wire hit_flag; 93 | 94 | // test process 95 | reg [31:0] clk_count; 96 | reg [31:0] bit_in_count; 97 | always @ (posedge clk) begin 98 | if (rst) begin 99 | bit <= 0; 100 | bit_valid <= 0; 101 | unique_bit_sequence <= 0; 102 | 103 | clk_count <= 1; 104 | bit_in_count <= 0; 105 | end else begin 106 | clk_count <= clk_count + 1; 107 | 108 | unique_bit_sequence <= ACCESS_ADDRESS; 109 | 110 | if (clk_count[3:0] == 0) begin // speed 1M 111 | if (bit_in_count < NUM_BIT_INPUT) begin 112 | bit <= search_unique_bit_sequence_test_input_mem[bit_in_count]; 113 | bit_valid <= 1; 114 | end 115 | bit_in_count <= bit_in_count + 1; 116 | end else begin 117 | bit_valid <= 0; 118 | end 119 | 120 | if (bit_in_count == (NUM_BIT_INPUT+30)) begin 121 | $display("%d input", NUM_BIT_INPUT); 122 | $finish; 123 | end 124 | 125 | // display while bit sequence hit 126 | if (hit_flag) begin 127 | $display("unique_bit_sequence full match at the %dth bit", bit_in_count); 128 | $display("unique_bit_sequence starting idx %d", bit_in_count - LEN_UNIQUE_BIT_SEQUENCE); 129 | $display("Compare the unique_bit_sequence starting idx and the search_unique_bit_sequence_test_output_ref_mem[0] ..."); 130 | if ((bit_in_count - LEN_UNIQUE_BIT_SEQUENCE) == search_unique_bit_sequence_test_output_ref_mem[0]) begin 131 | $display("Same as python result %d. Test PASS.", search_unique_bit_sequence_test_output_ref_mem[0]); 132 | end else begin 133 | $display("Different from python result %d", search_unique_bit_sequence_test_output_ref_mem[0]); 134 | end 135 | end 136 | 137 | end 138 | end 139 | 140 | search_unique_bit_sequence # ( 141 | .LEN_UNIQUE_BIT_SEQUENCE(LEN_UNIQUE_BIT_SEQUENCE) 142 | ) search_unique_bit_sequence_i ( 143 | .clk(clk), 144 | .rst(rst), 145 | 146 | .phy_bit(bit), 147 | .bit_valid(bit_valid), 148 | .unique_bit_sequence(unique_bit_sequence), 149 | 150 | .hit_flag(hit_flag) 151 | ); 152 | 153 | endmodule 154 | 155 | -------------------------------------------------------------------------------- /verilog/serial_in_ram_out.v: -------------------------------------------------------------------------------- 1 | // Author: Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | `timescale 1ns / 1ps 6 | module serial_in_ram_out # 7 | ( 8 | parameter DATA_WIDTH = 8, 9 | parameter ADDRESS_WIDTH = 6 10 | ) ( 11 | input wire clk, 12 | input wire rst, 13 | 14 | input wire [(DATA_WIDTH-1) : 0] data_in, 15 | input wire data_in_valid, 16 | 17 | input wire [(ADDRESS_WIDTH-1) : 0] addr, 18 | output wire [(DATA_WIDTH-1) : 0] data 19 | ); 20 | 21 | reg [(ADDRESS_WIDTH-1) : 0] addr_internal; 22 | 23 | always @ (posedge clk) begin 24 | if (rst) begin 25 | addr_internal <= 0; 26 | end else begin 27 | if (data_in_valid) begin 28 | addr_internal <= addr_internal + 1; 29 | end 30 | end 31 | end 32 | 33 | dpram # ( 34 | .DATA_WIDTH(DATA_WIDTH), 35 | .ADDRESS_WIDTH(ADDRESS_WIDTH) 36 | ) cos_table_dpram_i ( 37 | .clk(clk), 38 | .rst(rst), 39 | 40 | .write_address(addr_internal), 41 | .write_data(data_in), 42 | .write_enable(1'b1), 43 | 44 | .read_address(addr), 45 | .read_data(data) 46 | ); 47 | 48 | endmodule 49 | 50 | -------------------------------------------------------------------------------- /verilog/tx_clk_gen.v: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------- 2 | // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<< 3 | // -------------------------------------------------------------------- 4 | // Author: halftop 5 | // Github: https://github.com/halftop 6 | // Email: yu.zh@live.com 7 | // Description: uart_tx_baud_rate_clk_generate 8 | // Dependencies: 9 | // Since: 2019-06-07 15:36:59 10 | // LastEditors: halftop 11 | // LastEditTime: 2019-06-07 15:36:59 12 | // ******************************************************************** 13 | // Module Function: generate_uart_tx_baud_rate_clk 14 | `timescale 1ns / 1ps 15 | module tx_clk_gen 16 | #( 17 | parameter CLK_FREQUENCE = 50_000_000, //hz 18 | BAUD_RATE = 9600 //9600、19200 、38400 、57600 、115200、230400、460800、921600 19 | ) 20 | ( 21 | input clk , //system_clk 22 | input rst_n , //system_reset 23 | input tx_done , //once_tx_done 24 | input tx_start , //once_tx_start 25 | output reg bps_clk //baud_rate_clk 26 | ); 27 | 28 | localparam BPS_CNT = CLK_FREQUENCE/BAUD_RATE-1, 29 | BPS_WD = log2(BPS_CNT); 30 | 31 | reg [BPS_WD-1:0] count; 32 | reg c_state; 33 | reg n_state; 34 | //FSM-1 1'b0:IDLE 1'b1:send_data 35 | always @(posedge clk or negedge rst_n) begin 36 | if (!rst_n) 37 | c_state <= 1'b0; 38 | else 39 | c_state <= n_state; 40 | end 41 | //FSM-2 42 | always @(*) begin 43 | case (c_state) 44 | 1'b0: n_state = tx_start ? 1'b1 : 1'b0; 45 | 1'b1: n_state = tx_done ? 1'b0 : 1'b1; 46 | default: n_state = 1'b0; 47 | endcase 48 | end 49 | //FSM-3 FSM's output(count_en) is equal to c_state 50 | 51 | //baud_rate_clk_counter 52 | always @(posedge clk or negedge rst_n) begin 53 | if (!rst_n) 54 | count <= {BPS_WD{1'b0}}; 55 | else if (!c_state) 56 | count <= {BPS_WD{1'b0}}; 57 | else begin 58 | if (count == BPS_CNT) 59 | count <= {BPS_WD{1'b0}}; 60 | else 61 | count <= count + 1'b1; 62 | end 63 | end 64 | //baud_rate_clk_output 65 | always @(posedge clk or negedge rst_n) begin 66 | if (!rst_n) 67 | bps_clk <= 1'b0; 68 | else if (count == 'd1) 69 | bps_clk <= 1'b1; 70 | else 71 | bps_clk <= 1'b0; 72 | end 73 | //get_the_width_of_ 74 | function integer log2(input integer v); 75 | begin 76 | log2=0; 77 | while(v>>log2) 78 | log2=log2+1; 79 | end 80 | endfunction 81 | 82 | endmodule 83 | 84 | -------------------------------------------------------------------------------- /verilog/uart_frame_rx.v: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------- 2 | // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<< 3 | // -------------------------------------------------------------------- 4 | // Author: halftop 5 | // Github: https://github.com/halftop 6 | // Email: yu.zh@live.com 7 | // Description: 8 | // Dependencies: 9 | // Since: 2019-06-09 16:31:56 10 | // LastEditors: halftop 11 | // LastEditTime: 2019-06-09 16:31:56 12 | // ******************************************************************** 13 | // Module Function: 14 | `timescale 1ns / 1ps 15 | 16 | module uart_frame_rx 17 | #( 18 | parameter CLK_FREQUENCE = 50_000_000, //hz 19 | BAUD_RATE = 9600 , //9600、19200 、38400 、57600 、115200、230400、460800、921600 20 | PARITY = "NONE" , //"NONE","EVEN","ODD" 21 | FRAME_WD = 8 //if PARITY="NONE",it can be 5~9;else 5~8 22 | ) 23 | ( 24 | input clk , //sys_clk 25 | input rst_n , 26 | input uart_rx , 27 | output reg [FRAME_WD-1:0] rx_frame , //frame_received,when rx_done = 1 it's valid 28 | output reg rx_done , //once_rx_done 29 | output reg frame_error //when the PARITY is enable if frame_error = 1,the frame received is wrong 30 | ); 31 | 32 | wire sample_clk ; 33 | wire frame_en ; //once_rx_start 34 | reg cnt_en ; //sample_clk_cnt enable 35 | reg [3:0] sample_clk_cnt ; 36 | reg [log2(FRAME_WD+1)-1:0] sample_bit_cnt ; 37 | wire baud_rate_clk ; 38 | 39 | localparam IDLE = 5'b0_0000, 40 | START_BIT = 5'b0_0001, 41 | DATA_FRAME = 5'b0_0010, 42 | PARITY_BIT = 5'b0_0100, 43 | STOP_BIT = 5'b0_1000, 44 | DONE = 5'b1_0000; 45 | 46 | reg [4:0] cstate; 47 | reg [4:0] nstate; 48 | // 49 | wire [1:0] verify_mode; 50 | generate 51 | if (PARITY == "ODD") 52 | assign verify_mode = 2'b01; 53 | else if (PARITY == "EVEN") 54 | assign verify_mode = 2'b10; 55 | else 56 | assign verify_mode = 2'b00; 57 | endgenerate 58 | //detect the start condition--the negedge of uart_rx 59 | reg uart_rx0,uart_rx1,uart_rx2,uart_rx3; 60 | 61 | always @(posedge clk or negedge rst_n) begin 62 | if (!rst_n) begin 63 | uart_rx0 <= 1'b0; 64 | uart_rx1 <= 1'b0; 65 | uart_rx2 <= 1'b0; 66 | uart_rx3 <= 1'b0; 67 | end else begin 68 | uart_rx0 <= uart_rx ; 69 | uart_rx1 <= uart_rx0; 70 | uart_rx2 <= uart_rx1; 71 | uart_rx3 <= uart_rx2; 72 | end 73 | end 74 | //negedge of uart_rx-----start_bit 75 | assign frame_en = uart_rx3 & uart_rx2 & ~uart_rx1 & ~uart_rx0; 76 | 77 | always @(posedge clk or negedge rst_n) begin 78 | if (!rst_n) 79 | cnt_en <= 1'b0; 80 | else if (frame_en) 81 | cnt_en <= 1'b1; 82 | else if (rx_done) 83 | cnt_en <= 1'b0; 84 | else 85 | cnt_en <= cnt_en; 86 | end 87 | 88 | assign baud_rate_clk = sample_clk & sample_clk_cnt == 4'd8; 89 | 90 | always @(posedge clk or negedge rst_n) begin 91 | if (!rst_n) 92 | sample_clk_cnt <= 4'd0; 93 | else if (cnt_en) begin 94 | if (baud_rate_clk) 95 | sample_clk_cnt <= 4'd0; 96 | else if (sample_clk) 97 | sample_clk_cnt <= sample_clk_cnt + 1'b1; 98 | else 99 | sample_clk_cnt <= sample_clk_cnt; 100 | end else 101 | sample_clk_cnt <= 4'd0; 102 | end 103 | //the start_bit is the first one (0),then the LSB of the data_frame is the second(1) ...... 104 | always @(posedge clk or negedge rst_n) begin 105 | if (!rst_n) 106 | sample_bit_cnt <= 'd0; 107 | else if (cstate == IDLE) 108 | sample_bit_cnt <= 'd0; 109 | else if (baud_rate_clk) 110 | sample_bit_cnt <= sample_bit_cnt + 1'b1; 111 | else 112 | sample_bit_cnt <= sample_bit_cnt; 113 | end 114 | //read the readme 115 | reg [1:0] sample_result ; 116 | always @(posedge clk or negedge rst_n) begin 117 | if (!rst_n) 118 | sample_result <= 1'b0; 119 | else if (sample_clk) begin 120 | case (sample_clk_cnt) 121 | 4'd0:sample_result <= 2'd0; 122 | 4'd3,4'd4,4'd5: sample_result <= sample_result + uart_rx; 123 | default: sample_result <= sample_result; 124 | endcase 125 | end 126 | end 127 | //FSM-1 128 | always @(posedge clk or negedge rst_n) begin 129 | if (!rst_n) 130 | cstate <= IDLE; 131 | else 132 | cstate <= nstate; 133 | end 134 | //FSM-2 135 | always @(*) begin 136 | case (cstate) 137 | IDLE : nstate = frame_en ? START_BIT : IDLE ; 138 | START_BIT : nstate = (baud_rate_clk & sample_result[1] == 1'b0) ? DATA_FRAME : START_BIT ; 139 | DATA_FRAME : begin 140 | case (verify_mode[1]^verify_mode[0]) 141 | 1'b1: nstate = (sample_bit_cnt == FRAME_WD & baud_rate_clk) ? PARITY_BIT : DATA_FRAME ; //parity is enable 142 | 1'b0: nstate = (sample_bit_cnt == FRAME_WD & baud_rate_clk) ? STOP_BIT : DATA_FRAME ; //parity is disable 143 | default: nstate = (sample_bit_cnt == FRAME_WD & baud_rate_clk) ? STOP_BIT : DATA_FRAME ; //defasult is disable 144 | endcase 145 | end 146 | PARITY_BIT : nstate = baud_rate_clk ? STOP_BIT : PARITY_BIT ; 147 | STOP_BIT : nstate = (baud_rate_clk & sample_result[1] == 1'b1) ? DONE : STOP_BIT ; 148 | DONE : nstate = IDLE; 149 | default: nstate = IDLE; 150 | endcase 151 | end 152 | //FSM-3 153 | always @(posedge clk or negedge rst_n) begin 154 | if (!rst_n) begin 155 | rx_frame <= 'd0; 156 | rx_done <= 1'b0; 157 | frame_error <= 1'b0; 158 | end else begin 159 | case (nstate) 160 | IDLE : begin 161 | rx_frame <= 'd0; 162 | rx_done <= 1'b0; 163 | frame_error <= 1'b0; 164 | end 165 | START_BIT : begin 166 | rx_frame <= 'd0; 167 | rx_done <= 1'b0; 168 | frame_error <= 1'b0; 169 | end 170 | DATA_FRAME : begin 171 | if (sample_clk & sample_clk_cnt == 4'd6) 172 | rx_frame <= {sample_result[1],rx_frame[FRAME_WD-1:1]}; 173 | else 174 | rx_frame <= rx_frame; 175 | rx_done <= 1'b0; 176 | frame_error <= 1'b0; 177 | end 178 | PARITY_BIT : begin 179 | rx_frame <= rx_frame; 180 | rx_done <= 1'b0; 181 | if (sample_clk_cnt == 4'd8) 182 | frame_error <= ^rx_frame ^ sample_result[1]; 183 | else 184 | frame_error <= frame_error; 185 | end 186 | STOP_BIT : begin 187 | rx_frame <= rx_frame; 188 | rx_done <= 1'b0; 189 | frame_error <= frame_error; 190 | end 191 | DONE : begin 192 | frame_error <= frame_error; 193 | rx_done <= 1'b1; 194 | rx_frame <= rx_frame; 195 | end 196 | default: begin 197 | rx_frame <= rx_frame; 198 | rx_done <= 1'b0; 199 | frame_error <= frame_error; 200 | end 201 | endcase 202 | end 203 | end 204 | 205 | rx_clk_gen 206 | #( 207 | .CLK_FREQUENCE (CLK_FREQUENCE ), //hz 208 | .BAUD_RATE (BAUD_RATE ) //9600、19200 、38400 、57600 、115200、230400、460800、921600 209 | ) 210 | rx_clk_gen_inst 211 | ( 212 | .clk ( clk ) , 213 | .rst_n ( rst_n ) , 214 | .rx_start ( frame_en ) , 215 | .rx_done ( rx_done ) , 216 | .sample_clk ( sample_clk ) 217 | ); 218 | 219 | function integer log2(input integer v); 220 | begin 221 | log2=0; 222 | while(v>>log2) 223 | log2=log2+1; 224 | end 225 | endfunction 226 | endmodule -------------------------------------------------------------------------------- /verilog/uart_frame_tx.v: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------- 2 | // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<< 3 | // -------------------------------------------------------------------- 4 | // Author: halftop 5 | // Github: https://github.com/halftop 6 | // Email: yu.zh@live.com 7 | // Description: 8 | // Dependencies: 9 | // Since: 2019-06-08 16:51:59 10 | // LastEditors: halftop 11 | // LastEditTime: 2019-06-08 16:51:59 12 | // ******************************************************************** 13 | // Module Function: 14 | `timescale 1ns / 1ps 15 | module uart_frame_tx 16 | #( 17 | parameter CLK_FREQUENCE = 50_000_000, //hz 18 | BAUD_RATE = 9600 , //9600、19200 、38400 、57600 、115200、230400、460800、921600 19 | PARITY = "NONE" , //"NONE","EVEN","ODD" 20 | FRAME_WD = 8 //if PARITY="NONE",it can be 5~9;else 5~8 21 | ) 22 | ( 23 | input clk , //system_clk 24 | input rst_n , //system_reset 25 | input frame_en , //once_tx_start 26 | input [FRAME_WD-1:0] data_frame , //data_to_tx 27 | output reg tx_done , //once_tx_done 28 | output reg uart_tx //uart_tx_data 29 | ); 30 | 31 | wire bps_clk; 32 | 33 | tx_clk_gen 34 | #( 35 | .CLK_FREQUENCE (CLK_FREQUENCE), //hz 36 | .BAUD_RATE (BAUD_RATE ) //9600、19200 、38400 、57600 、115200、230400、460800、921600 37 | ) 38 | tx_clk_gen_inst 39 | ( 40 | .clk ( clk ), //system_clk 41 | .rst_n ( rst_n ), //system_reset 42 | .tx_done ( tx_done ), //once_tx_done 43 | .tx_start ( frame_en ), //once_tx_start 44 | .bps_clk ( bps_clk ) //baud_rate_clk 45 | ); 46 | 47 | localparam IDLE = 6'b00_0000 , 48 | READY = 6'b00_0001 , 49 | START_BIT = 6'b00_0010 , 50 | SHIFT_PRO = 6'b00_0100 , 51 | PARITY_BIT = 6'b00_1000 , 52 | STOP_BIT = 6'b01_0000 , 53 | DONE = 6'b10_0000 ; 54 | 55 | wire [1:0] verify_mode; 56 | generate 57 | if (PARITY == "ODD") 58 | assign verify_mode = 2'b01; 59 | else if (PARITY == "EVEN") 60 | assign verify_mode = 2'b10; 61 | else 62 | assign verify_mode = 2'b00; 63 | endgenerate 64 | 65 | reg [FRAME_WD-1:0] data_reg ; 66 | reg [log2(FRAME_WD-1)-1:0] cnt ; 67 | reg parity_even ; 68 | reg [5:0] cstate ; 69 | reg [5:0] nstate ; 70 | 71 | always @(posedge clk or negedge rst_n) begin 72 | if (!rst_n) 73 | cnt <= 'd0; 74 | else if (cstate == SHIFT_PRO & bps_clk == 1'b1) 75 | if (cnt == FRAME_WD-1) 76 | cnt <= 'd0; 77 | else 78 | cnt <= cnt + 1'b1; 79 | else 80 | cnt <= cnt; 81 | end 82 | //FSM-1 83 | always @(posedge clk or negedge rst_n) begin 84 | if (!rst_n) 85 | cstate <= IDLE; 86 | else 87 | cstate <= nstate; 88 | end 89 | //FSM-2 90 | always @(*) begin 91 | case (cstate) 92 | IDLE : nstate = frame_en ? READY : IDLE ; 93 | READY : nstate = (bps_clk == 1'b1) ? START_BIT : READY; 94 | START_BIT : nstate = (bps_clk == 1'b1) ? SHIFT_PRO : START_BIT; 95 | SHIFT_PRO : nstate = (cnt == FRAME_WD-1 & bps_clk == 1'b1) ? PARITY_BIT : SHIFT_PRO; 96 | PARITY_BIT : nstate = (bps_clk == 1'b1) ? STOP_BIT : PARITY_BIT; 97 | STOP_BIT : nstate = (bps_clk == 1'b1) ? DONE : STOP_BIT; 98 | DONE : nstate = IDLE; 99 | default : nstate = IDLE; 100 | endcase 101 | end 102 | //FSM-3 103 | always @(posedge clk or negedge rst_n) begin 104 | if (!rst_n) begin 105 | data_reg <= 'd0; 106 | uart_tx <= 1'b1; 107 | tx_done <= 1'b0; 108 | parity_even <= 1'b0; 109 | end else begin 110 | case (nstate) 111 | IDLE : begin 112 | data_reg <= 'd0; 113 | tx_done <= 1'b0; 114 | uart_tx <= 1'b1; 115 | end 116 | READY : begin 117 | data_reg <= 'd0; 118 | tx_done <= 1'b0; 119 | uart_tx <= 1'b1; 120 | end 121 | START_BIT : begin 122 | data_reg <= data_frame; 123 | parity_even <= ^data_frame; 124 | uart_tx <= 1'b0; 125 | tx_done <= 1'b0; 126 | end 127 | SHIFT_PRO : begin 128 | if(bps_clk == 1'b1) begin 129 | data_reg <= {1'b0,data_reg[FRAME_WD-1:1]}; 130 | uart_tx <= data_reg[0]; 131 | end else begin 132 | data_reg <= data_reg; 133 | uart_tx <= uart_tx; 134 | end 135 | tx_done <= 1'b0; 136 | end 137 | PARITY_BIT : begin 138 | data_reg <= data_reg; 139 | tx_done <= 1'b0; 140 | case (verify_mode) 141 | 2'b00: uart_tx <= 1'b1; //若无校验多发一位STOP_BIT 142 | 2'b01: uart_tx <= ~parity_even; 143 | 2'b10: uart_tx <= parity_even; 144 | default: uart_tx <= 1'b1; 145 | endcase 146 | end 147 | STOP_BIT : uart_tx <= 1'b1; 148 | DONE : tx_done <= 1'b1; 149 | default : begin 150 | data_reg <= 'd0; 151 | uart_tx <= 1'b1; 152 | tx_done <= 1'b0; 153 | parity_even <= 1'b0; 154 | end 155 | endcase 156 | end 157 | end 158 | 159 | function integer log2(input integer v); 160 | begin 161 | log2=0; 162 | while(v>>log2) 163 | log2=log2+1; 164 | end 165 | endfunction 166 | 167 | endmodule -------------------------------------------------------------------------------- /verilog/vco.v: -------------------------------------------------------------------------------- 1 | // Author: Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | // Core_v5.3 section 3.1on page 2640 6 | // The modulation index shall be between 0.45 and 0.55 7 | // We implement 0.5 8 | 9 | `timescale 1ns / 1ps 10 | module vco # 11 | ( 12 | parameter VCO_BIT_WIDTH = 16, 13 | parameter SIN_COS_ADDR_BIT_WIDTH = 11, 14 | parameter IQ_BIT_WIDTH = 8 15 | ) ( 16 | input wire clk, 17 | input wire rst, 18 | 19 | input wire [(SIN_COS_ADDR_BIT_WIDTH-1) : 0] cos_table_write_address, 20 | input wire signed [(IQ_BIT_WIDTH-1) : 0] cos_table_write_data, 21 | input wire [(SIN_COS_ADDR_BIT_WIDTH-1) : 0] sin_table_write_address, 22 | input wire signed [(IQ_BIT_WIDTH-1) : 0] sin_table_write_data, 23 | 24 | input wire signed [(VCO_BIT_WIDTH-1) : 0] voltage_signal, 25 | input wire voltage_signal_valid, 26 | input wire voltage_signal_valid_last, 27 | 28 | output wire signed [(IQ_BIT_WIDTH-1) : 0] cos_out, 29 | output wire signed [(IQ_BIT_WIDTH-1) : 0] sin_out, 30 | output reg sin_cos_out_valid, 31 | output reg sin_cos_out_valid_last 32 | ); 33 | 34 | reg signed [(VCO_BIT_WIDTH-1) : 0] integral_voltage_signal; 35 | 36 | always @ (posedge clk) begin 37 | if (rst) begin 38 | sin_cos_out_valid <= 0; 39 | sin_cos_out_valid_last <= 0; 40 | 41 | integral_voltage_signal <= 0; 42 | end else begin 43 | sin_cos_out_valid <= voltage_signal_valid; 44 | sin_cos_out_valid_last <= voltage_signal_valid_last; 45 | 46 | if (voltage_signal_valid) begin 47 | integral_voltage_signal <= integral_voltage_signal + voltage_signal; 48 | end 49 | end 50 | end 51 | 52 | dpram # ( 53 | .DATA_WIDTH(IQ_BIT_WIDTH), 54 | .ADDRESS_WIDTH(SIN_COS_ADDR_BIT_WIDTH) 55 | ) cos_table_dpram_i ( 56 | .clk(clk), 57 | .rst(rst), 58 | 59 | .write_address(cos_table_write_address), 60 | .write_data(cos_table_write_data), 61 | .write_enable(1'b1), 62 | 63 | .read_address(integral_voltage_signal[(SIN_COS_ADDR_BIT_WIDTH-1) : 0]), 64 | .read_data(cos_out) 65 | ); 66 | 67 | dpram # ( 68 | .DATA_WIDTH(IQ_BIT_WIDTH), 69 | .ADDRESS_WIDTH(SIN_COS_ADDR_BIT_WIDTH) 70 | ) sin_table_dpram_i ( 71 | .clk(clk), 72 | .rst(rst), 73 | 74 | .write_address(sin_table_write_address), 75 | .write_data(sin_table_write_data), 76 | .write_enable(1'b1), 77 | 78 | .read_address(integral_voltage_signal[(SIN_COS_ADDR_BIT_WIDTH-1) : 0]), 79 | .read_data(sin_out) 80 | ); 81 | 82 | endmodule 83 | 84 | -------------------------------------------------------------------------------- /verilog/vco_tb.v: -------------------------------------------------------------------------------- 1 | // Author: Xianjun Jiao 2 | // SPDX-FileCopyrightText: 2024 Xianjun Jiao 3 | // SPDX-License-Identifier: Apache-2.0 license 4 | 5 | // To generate test vector and result reference, in python directory run: 6 | // python3 test_vector_for_btle_verilog.py 7 | // (arguments can be added: example_idx snr ppm_value) 8 | // Run verilog simulation: 9 | // iverilog -o vco_tb vco_tb.v vco.v dpram.v 10 | // vvp vco_tb 11 | // Check verilog outputs to see whether test pass. 12 | 13 | `timescale 1ns / 1ps 14 | module vco_tb # 15 | ( 16 | parameter VCO_BIT_WIDTH = 16, 17 | parameter SIN_COS_ADDR_BIT_WIDTH = 11, 18 | parameter IQ_BIT_WIDTH = 8 19 | ) ( 20 | ); 21 | 22 | reg clk; 23 | reg rst; 24 | 25 | reg [64*8:0] COS_TABLE_FILENAME = "cos_table.txt"; 26 | reg [64*8:0] SIN_TABLE_FILENAME = "sin_table.txt"; 27 | reg [64*8:0] TEST_INPUT_FILENAME = "btle_tx_vco_test_input.txt"; 28 | reg [64*8:0] TEST_OUTPUT_COS_REF_FILENAME = "btle_tx_vco_test_output_cos_ref.txt"; 29 | reg [64*8:0] TEST_OUTPUT_SIN_REF_FILENAME = "btle_tx_vco_test_output_sin_ref.txt"; 30 | reg [64*8:0] TEST_OUTPUT_COS_FILENAME = "btle_tx_vco_test_output_cos.txt"; 31 | reg [64*8:0] TEST_OUTPUT_SIN_FILENAME = "btle_tx_vco_test_output_sin.txt"; 32 | 33 | reg signed [(IQ_BIT_WIDTH-1):0] cos_table_mem [0:4095]; 34 | reg signed [(IQ_BIT_WIDTH-1):0] sin_table_mem [0:4095]; 35 | reg signed [(VCO_BIT_WIDTH-1):0] vco_test_input_mem [0:4095]; 36 | reg signed [(IQ_BIT_WIDTH-1):0] vco_test_output_cos_mem [0:4095]; 37 | reg signed [(IQ_BIT_WIDTH-1):0] vco_test_output_sin_mem [0:4095]; 38 | reg signed [(IQ_BIT_WIDTH-1):0] vco_test_output_cos_ref_mem [0:4095]; 39 | reg signed [(IQ_BIT_WIDTH-1):0] vco_test_output_sin_ref_mem [0:4095]; 40 | 41 | integer vco_test_input_fd; 42 | integer vco_test_output_cos_fd; 43 | integer vco_test_output_sin_fd; 44 | integer vco_test_output_cos_ref_fd; 45 | integer vco_test_output_sin_ref_fd; 46 | integer cos_table_fd; 47 | integer sin_table_fd; 48 | integer NUM_SAMPLE_INPUT; 49 | integer NUM_SAMPLE_OUTPUT; 50 | integer NUM_ERROR; 51 | integer tmp; 52 | integer i, j; 53 | 54 | initial begin 55 | $dumpfile("vco_tb.vcd"); 56 | $dumpvars; 57 | 58 | // read cos and sin table 59 | cos_table_fd = $fopen(COS_TABLE_FILENAME, "r"); 60 | for (i=0; i<(1< 0) begin 203 | $display("%d error found!", NUM_ERROR); 204 | $display("Please check %s VS %s", TEST_OUTPUT_COS_FILENAME, TEST_OUTPUT_COS_REF_FILENAME); 205 | end else begin 206 | $display("%d error found! output cos Test PASS.", NUM_ERROR); 207 | end 208 | 209 | $display("Compare the vco_test_output_sin_mem and the vco_test_output_sin_ref_mem ..."); 210 | NUM_ERROR = 0; 211 | for (i=0; i 0) begin 217 | $display("%d error found!", NUM_ERROR); 218 | $display("Please check %s VS %s", TEST_OUTPUT_SIN_FILENAME, TEST_OUTPUT_SIN_REF_FILENAME); 219 | end else begin 220 | $display("%d error found! output sin Test PASS.", NUM_ERROR); 221 | end 222 | 223 | $finish; 224 | end 225 | 226 | // record the result 227 | if (sin_cos_out_valid) begin 228 | vco_test_output_cos_mem[sample_out_count] <= cos_out; 229 | vco_test_output_sin_mem[sample_out_count] <= sin_out; 230 | sample_out_count <= sample_out_count + 1; 231 | end 232 | 233 | end 234 | end 235 | end 236 | 237 | vco # ( 238 | .VCO_BIT_WIDTH(VCO_BIT_WIDTH), 239 | .SIN_COS_ADDR_BIT_WIDTH(SIN_COS_ADDR_BIT_WIDTH), 240 | .IQ_BIT_WIDTH(IQ_BIT_WIDTH) 241 | ) vco_i ( 242 | .clk(clk), 243 | .rst(rst), 244 | 245 | .cos_table_write_address(cos_table_write_address), 246 | .cos_table_write_data(cos_table_write_data), 247 | .sin_table_write_address(sin_table_write_address), 248 | .sin_table_write_data(sin_table_write_data), 249 | 250 | .voltage_signal(voltage_signal), 251 | .voltage_signal_valid(voltage_signal_valid), 252 | 253 | .cos_out(cos_out), 254 | .sin_out(sin_out), 255 | .sin_cos_out_valid(sin_cos_out_valid) 256 | ); 257 | 258 | endmodule 259 | 260 | --------------------------------------------------------------------------------