diff options
Diffstat (limited to 'host/lib/usrp/b200')
-rw-r--r-- | host/lib/usrp/b200/b200_iface.cpp | 183 | ||||
-rw-r--r-- | host/lib/usrp/b200/b200_iface.hpp | 45 | ||||
-rw-r--r-- | host/lib/usrp/b200/b200_impl.cpp | 60 | ||||
-rw-r--r-- | host/lib/usrp/b200/b200_impl.hpp | 9 | ||||
-rw-r--r-- | host/lib/usrp/b200/b200_io_impl.cpp | 3 | ||||
-rw-r--r-- | host/lib/usrp/b200/b200_regs.hpp | 2 |
6 files changed, 97 insertions, 205 deletions
diff --git a/host/lib/usrp/b200/b200_iface.cpp b/host/lib/usrp/b200/b200_iface.cpp index 4754a6357..207c418fc 100644 --- a/host/lib/usrp/b200/b200_iface.cpp +++ b/host/lib/usrp/b200/b200_iface.cpp @@ -17,6 +17,7 @@ #include "b200_iface.hpp" +#include "../../utils/ihex.hpp" #include <uhd/config.hpp> #include <uhd/utils/msg.hpp> #include <uhd/utils/log.hpp> @@ -87,7 +88,7 @@ typedef boost::uint32_t hash_type; **********************************************************************/ /*! * Create a file hash - * The hash will be used to identify the loaded firmware and fpga image + * The hash will be used to identify the loaded fpga image * \param filename file used to generate hash value * \return hash value in a uint32_t type */ @@ -125,66 +126,6 @@ static hash_type generate_hash(const char *filename) } -/*! - * Verify checksum of a Intel HEX record - * \param record a line from an Intel HEX file - * \return true if record is valid, false otherwise - */ -bool checksum(const std::string& record) { - - size_t len = record.length(); - unsigned int i; - unsigned char sum = 0; - unsigned int val; - - for (i = 1; i < len; i += 2) { - std::istringstream(record.substr(i, 2)) >> std::hex >> val; - sum += val; - } - - if (sum == 0) - return true; - else - return false; -} - - -/*! - * Parse Intel HEX record - * - * \param record a line from an Intel HEX file - * \param len output length of record - * \param addr output address - * \param type output type - * \param data output data - * \return true if record is sucessfully read, false on error - */ -bool parse_record(const std::string& record, boost::uint16_t &len, \ - boost::uint16_t &addr, boost::uint16_t &type, unsigned char* data) { - - unsigned int i; - std::string _data; - unsigned int val; - - if (record.substr(0, 1) != ":") - return false; - - std::istringstream(record.substr(1, 2)) >> std::hex >> len; - std::istringstream(record.substr(3, 4)) >> std::hex >> addr; - std::istringstream(record.substr(7, 2)) >> std::hex >> type; - - if (len > (2 * (record.length() - 9))) // sanity check to prevent buffer overrun - return false; - - for (i = 0; i < len; i++) { - std::istringstream(record.substr(9 + 2 * i, 2)) >> std::hex >> val; - data[i] = (unsigned char) val; - } - - return true; -} - - /*********************************************************************** * The implementation class **********************************************************************/ @@ -270,109 +211,31 @@ public: void load_firmware(const std::string filestring, UHD_UNUSED(bool force) = false) { - const char *filename = filestring.c_str(); - - /* Fields used in each USB control transfer. */ - boost::uint16_t len = 0; - boost::uint16_t type = 0; - boost::uint16_t lower_address_bits = 0x0000; - unsigned char data[512]; - - /* Can be set by the Intel HEX record 0x04, used for all 0x00 records - * thereafter. Note this field takes the place of the 'index' parameter in - * libusb calls, and is necessary for FX3's 32-bit addressing. */ - boost::uint16_t upper_address_bits = 0x0000; - - std::ifstream file; - file.open(filename, std::ifstream::in); - - if(!file.good()) { - throw uhd::io_error("fx3_load_firmware: cannot open firmware input file"); + if (load_img_msg) + UHD_MSG(status) << "Loading firmware image: " + << filestring << "..." << std::flush; + + ihex_reader file_reader(filestring); + try { + file_reader.read( + boost::bind( + &b200_iface_impl::fx3_control_write, this, + FX3_FIRMWARE_LOAD, _1, _2, _3, _4, 0 + ) + ); + } catch (const uhd::io_error &e) { + throw uhd::io_error(str(boost::format("Could not load firmware: \n%s") % e.what())); } - if (load_img_msg) UHD_MSG(status) << "Loading firmware image: " \ - << filestring << "..." << std::flush; - - while (!file.eof()) { - boost::int32_t ret = 0; - std::string record; - file >> record; - - if (!(record.length() > 0)) - continue; - - /* Check for valid Intel HEX record. */ - if (!checksum(record) || !parse_record(record, len, \ - lower_address_bits, type, data)) { - throw uhd::io_error("fx3_load_firmware: bad intel hex record checksum"); - } - - /* Type 0x00: Data. */ - if (type == 0x00) { - ret = fx3_control_write(FX3_FIRMWARE_LOAD, \ - lower_address_bits, upper_address_bits, data, len); - - if (ret < 0) { - throw uhd::io_error("usrp_load_firmware: usrp_control_write failed"); - } - } - - /* Type 0x01: EOF. */ - else if (type == 0x01) { - if (lower_address_bits != 0x0000 || len != 0 ) { - throw uhd::io_error("fx3_load_firmware: For EOF record, address must be 0, length must be 0."); - } - - //TODO - //usrp_set_firmware_hash(hash); //set hash before reset - - /* Successful termination! */ - file.close(); + UHD_MSG(status) << std::endl; - /* Let the system settle. */ - boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); - return; - } - - /* Type 0x04: Extended Linear Address Record. */ - else if (type == 0x04) { - if (lower_address_bits != 0x0000 || len != 2 ) { - throw uhd::io_error("fx3_load_firmware: For ELA record, address must be 0, length must be 2."); - } - - upper_address_bits = ((boost::uint16_t)((data[0] & 0x00FF) << 8))\ - + ((boost::uint16_t)(data[1] & 0x00FF)); - } - - /* Type 0x05: Start Linear Address Record. */ - else if (type == 0x05) { - if (lower_address_bits != 0x0000 || len != 4 ) { - throw uhd::io_error("fx3_load_firmware: For SLA record, address must be 0, length must be 4."); - } - - /* The firmware load is complete. We now need to tell the CPU - * to jump to an execution address start point, now contained within - * the data field. Parse these address bits out, and then push the - * instruction. */ - upper_address_bits = ((boost::uint16_t)((data[0] & 0x00FF) << 8))\ - + ((boost::uint16_t)(data[1] & 0x00FF)); - lower_address_bits = ((boost::uint16_t)((data[2] & 0x00FF) << 8))\ - + ((boost::uint16_t)(data[3] & 0x00FF)); - - fx3_control_write(FX3_FIRMWARE_LOAD, lower_address_bits, \ - upper_address_bits, 0, 0); - - if (load_img_msg) UHD_MSG(status) << " done" << std::endl; - } - - /* If we receive an unknown record type, error out. */ - else { - throw uhd::io_error("fx3_load_firmware: unsupported record type."); - } - } + //TODO + //usrp_set_firmware_hash(hash); //set hash before reset - /* There was no valid EOF. */ - throw uhd::io_error("fx3_load_firmware: No EOF record found."); + /* Success! Let the system settle. */ + // TODO: Replace this with a polling loop in the FX3, or find out + // what the actual, correct timeout value is. + boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); } void reset_fx3(void) { diff --git a/host/lib/usrp/b200/b200_iface.hpp b/host/lib/usrp/b200/b200_iface.hpp index 19ec561fa..e45c78d49 100644 --- a/host/lib/usrp/b200/b200_iface.hpp +++ b/host/lib/usrp/b200/b200_iface.hpp @@ -30,25 +30,28 @@ enum b200_product_t { B200, B210, - B205 + B200MINI, + B205MINI }; // These are actual USB PIDs (not Ettus Product IDs) -const static boost::uint16_t B200_VENDOR_ID = 0x2500; -const static boost::uint16_t B200_VENDOR_NI_ID = 0x3923; -const static boost::uint16_t B200_PRODUCT_ID = 0x0020; -const static boost::uint16_t B205_PRODUCT_ID = 0x0021; -const static boost::uint16_t B200_PRODUCT_NI_ID = 0x7813; -const static boost::uint16_t B210_PRODUCT_NI_ID = 0x7814; -const static boost::uint16_t FX3_VID = 0x04b4; -const static boost::uint16_t FX3_DEFAULT_PID = 0x00f3; -const static boost::uint16_t FX3_REENUM_PID = 0x00f0; +const static boost::uint16_t B200_VENDOR_ID = 0x2500; +const static boost::uint16_t B200_VENDOR_NI_ID = 0x3923; +const static boost::uint16_t B200_PRODUCT_ID = 0x0020; +const static boost::uint16_t B200MINI_PRODUCT_ID = 0x0021; +const static boost::uint16_t B205MINI_PRODUCT_ID = 0x0022; +const static boost::uint16_t B200_PRODUCT_NI_ID = 0x7813; +const static boost::uint16_t B210_PRODUCT_NI_ID = 0x7814; +const static boost::uint16_t FX3_VID = 0x04b4; +const static boost::uint16_t FX3_DEFAULT_PID = 0x00f3; +const static boost::uint16_t FX3_REENUM_PID = 0x00f0; //! Map the USB PID to the product (only for PIDs that map to a single product) static const uhd::dict<boost::uint16_t, b200_product_t> B2XX_PID_TO_PRODUCT = boost::assign::map_list_of - (B200_PRODUCT_NI_ID, B200) - (B210_PRODUCT_NI_ID, B210) - (B205_PRODUCT_ID, B205) + (B200_PRODUCT_NI_ID, B200) + (B210_PRODUCT_NI_ID, B210) + (B200MINI_PRODUCT_ID, B200MINI) + (B205MINI_PRODUCT_ID, B205MINI) ; static const std::string B200_FW_FILE_NAME = "usrp_b200_fw.hex"; @@ -61,21 +64,25 @@ static const uhd::dict<boost::uint16_t, b200_product_t> B2XX_PRODUCT_ID = boost: (0x0002, B210) (0x7738, B210) (B210_PRODUCT_NI_ID, B210) - (0x0003, B205) - (0x7739, B205) + (0x0003, B200MINI) + (0x7739, B200MINI) + (0x0004, B205MINI) + (0x773a, B205MINI) ; static const uhd::dict<b200_product_t, std::string> B2XX_STR_NAMES = boost::assign::map_list_of - (B200, "B200") - (B210, "B210") - (B205, "B200mini") + (B200, "B200") + (B210, "B210") + (B200MINI, "B200mini") + (B205MINI, "B205mini") ; static const uhd::dict<b200_product_t, std::string> B2XX_FPGA_FILE_NAME = boost::assign::map_list_of (B200, "usrp_b200_fpga.bin") (B210, "usrp_b210_fpga.bin") - (B205, "usrp_b200mini_fpga.bin") + (B200MINI, "usrp_b200mini_fpga.bin") + (B205MINI, "usrp_b205mini_fpga.bin") ; diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index 3aaf28ab3..62690f09f 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -75,9 +75,9 @@ public: }; // B205 -class b205_ad9361_client_t : public ad9361_params { +class b2xxmini_ad9361_client_t : public ad9361_params { public: - ~b205_ad9361_client_t() {} + ~b2xxmini_ad9361_client_t() {} double get_band_edge(frequency_band_t band) { switch (band) { case AD9361_RX_BAND0: return 0; // Set these all to @@ -319,7 +319,8 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s else if (specified_vid) { vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid, B200_PRODUCT_ID)); - vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid, B205_PRODUCT_ID)); + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid, B200MINI_PRODUCT_ID)); + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid, B205MINI_PRODUCT_ID)); vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid, B200_PRODUCT_NI_ID)); vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid, B210_PRODUCT_NI_ID)); } @@ -333,7 +334,8 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s else { vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B200_PRODUCT_ID)); - vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B205_PRODUCT_ID)); + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B200MINI_PRODUCT_ID)); + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B205MINI_PRODUCT_ID)); vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID, B200_PRODUCT_NI_ID)); vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID, B210_PRODUCT_NI_ID)); } @@ -387,7 +389,7 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s UHD_MSG(status) << "Detected Device: " << B2XX_STR_NAMES[_product] << std::endl; - _gpsdo_capable = (_product != B205); + _gpsdo_capable = (not (_product == B200MINI or _product == B205MINI)); //////////////////////////////////////////////////////////////////// // Set up frontend mapping @@ -406,7 +408,7 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s _fe2 = 0; _gpio_state.swap_atr = 1; // Unswapped setup: - if (_product == B205 or (_product == B200 and _revision >= 5)) { + if (_product == B200MINI or _product == B205MINI or (_product == B200 and _revision >= 5)) { _fe1 = 0; //map radio0 to FE1 _fe2 = 1; //map radio1 to FE2 _gpio_state.swap_atr = 0; // ATRs for radio0 are mapped to FE1 @@ -513,7 +515,7 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s //////////////////////////////////////////////////////////////////// _tree->create<std::string>("/name").set("B-Series Device"); _tree->create<std::string>(mb_path / "name").set(product_name); - _tree->create<std::string>(mb_path / "codename").set((_product == B205) ? "Pixie" : "Sasquatch"); + _tree->create<std::string>(mb_path / "codename").set((_product == B200MINI or _product == B205MINI) ? "Pixie" : "Sasquatch"); //////////////////////////////////////////////////////////////////// // Create data transport @@ -541,7 +543,7 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s // create time and clock control objects //////////////////////////////////////////////////////////////////// _spi_iface = b200_local_spi_core::make(_local_ctrl); - if (_product != B205) { + if (not (_product == B200MINI or _product == B205MINI)) { _adf4001_iface = boost::make_shared<b200_ref_pll_ctrl>(_spi_iface); } @@ -550,13 +552,13 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s //////////////////////////////////////////////////////////////////// UHD_MSG(status) << "Initialize CODEC control..." << std::endl; ad9361_params::sptr client_settings; - if (_product == B205) { - client_settings = boost::make_shared<b205_ad9361_client_t>(); + if (_product == B200MINI or _product == B205MINI) { + client_settings = boost::make_shared<b2xxmini_ad9361_client_t>(); } else { client_settings = boost::make_shared<b200_ad9361_client_t>(); } _codec_ctrl = ad9361_ctrl::make_spi(client_settings, _spi_iface, AD9361_SLAVENO); - + //////////////////////////////////////////////////////////////////// // create codec control objects //////////////////////////////////////////////////////////////////// @@ -624,15 +626,18 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s //register time now and pps onto available radio cores _tree->create<time_spec_t>(mb_path / "time" / "now") - .publish(boost::bind(&time_core_3000::get_time_now, _radio_perifs[0].time64)); + .publish(boost::bind(&time_core_3000::get_time_now, _radio_perifs[0].time64)) + .subscribe(boost::bind(&b200_impl::set_time, this, _1)) + .set(0.0); + //re-sync the times when the tick rate changes + _tree->access<double>(mb_path / "tick_rate") + .subscribe(boost::bind(&b200_impl::sync_times, this)); _tree->create<time_spec_t>(mb_path / "time" / "pps") .publish(boost::bind(&time_core_3000::get_time_last_pps, _radio_perifs[0].time64)); - for (size_t i = 0; i < _radio_perifs.size(); i++) + BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs) { - _tree->access<time_spec_t>(mb_path / "time" / "now") - .subscribe(boost::bind(&time_core_3000::set_time_now, _radio_perifs[i].time64, _1)); _tree->access<time_spec_t>(mb_path / "time" / "pps") - .subscribe(boost::bind(&time_core_3000::set_time_next_pps, _radio_perifs[i].time64, _1)); + .subscribe(boost::bind(&time_core_3000::set_time_next_pps, perif.time64, _1)); } //setup time source props @@ -945,7 +950,7 @@ void b200_impl::check_fpga_compat(void) if (signature != 0xACE0BA5E) throw uhd::runtime_error( "b200::check_fpga_compat signature register readback failed"); - const boost::uint16_t expected = (_product == B205 ? B205_FPGA_COMPAT_NUM : B200_FPGA_COMPAT_NUM); + const boost::uint16_t expected = ((_product == B200MINI or _product == B205MINI) ? B205_FPGA_COMPAT_NUM : B200_FPGA_COMPAT_NUM); if (compat_major != expected) { throw uhd::runtime_error(str(boost::format( @@ -970,7 +975,7 @@ void b200_impl::set_mb_eeprom(const uhd::usrp::mboard_eeprom_t &mb_eeprom) void b200_impl::update_clock_source(const std::string &source) { // For B205, ref_sel selects whether or not to lock to the external clock source - if (_product == B205) + if (_product == B200MINI or _product == B205MINI) { if (source == "external" and _time_source == EXTERNAL) { @@ -1032,7 +1037,7 @@ void b200_impl::update_clock_source(const std::string &source) void b200_impl::update_time_source(const std::string &source) { - if (_product == B205 and source == "external" and _gpio_state.ref_sel == 1) + if ((_product == B200MINI or _product == B205MINI) and source == "external" and _gpio_state.ref_sel == 1) { throw uhd::value_error("external reference cannot be both a time source and a clock source"); } @@ -1052,11 +1057,24 @@ void b200_impl::update_time_source(const std::string &source) throw uhd::key_error("update_time_source: unknown source: " + source); if (_time_source != value) { - _local_ctrl->poke32(TOREG(SR_CORE_PPS_SEL), value); + _local_ctrl->poke32(TOREG(SR_CORE_SYNC), value); _time_source = value; } } +void b200_impl::set_time(const uhd::time_spec_t& t) +{ + BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs) + perif.time64->set_time_sync(t); + _local_ctrl->poke32(TOREG(SR_CORE_SYNC), 1 << 2 | boost::uint32_t(_time_source)); + _local_ctrl->poke32(TOREG(SR_CORE_SYNC), _time_source); +} + +void b200_impl::sync_times() +{ + set_time(_radio_perifs[0].time64->get_time_now()); +} + /*********************************************************************** * GPIO setup **********************************************************************/ @@ -1064,7 +1082,7 @@ void b200_impl::update_time_source(const std::string &source) void b200_impl::update_bandsel(const std::string& which, double freq) { // B205 does not have bandsels - if (_product == B205) { + if (_product == B200MINI or _product == B205MINI) { return; } diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index b406572fb..08ae68e9a 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -49,8 +49,8 @@ #include "recv_packet_demuxer_3000.hpp" static const boost::uint8_t B200_FW_COMPAT_NUM_MAJOR = 8; static const boost::uint8_t B200_FW_COMPAT_NUM_MINOR = 0; -static const boost::uint16_t B200_FPGA_COMPAT_NUM = 12; -static const boost::uint16_t B205_FPGA_COMPAT_NUM = 3; +static const boost::uint16_t B200_FPGA_COMPAT_NUM = 13; +static const boost::uint16_t B205_FPGA_COMPAT_NUM = 4; static const double B200_BUS_CLOCK_RATE = 100e6; static const boost::uint32_t B200_GPSDO_ST_NONE = 0x83; static const size_t B200_MAX_RATE_USB2 = 53248000; // bytes/s @@ -95,7 +95,8 @@ static const unsigned char B200_USB_DATA_SEND_ENDPOINT = 2; static std::vector<uhd::transport::usb_device_handle::vid_pid_pair_t> b200_vid_pid_pairs = boost::assign::list_of (uhd::transport::usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B200_PRODUCT_ID)) - (uhd::transport::usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B205_PRODUCT_ID)) + (uhd::transport::usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B200MINI_PRODUCT_ID)) + (uhd::transport::usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B205MINI_PRODUCT_ID)) (uhd::transport::usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID, B200_PRODUCT_NI_ID)) (uhd::transport::usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID, B210_PRODUCT_NI_ID)) ; @@ -167,6 +168,8 @@ private: uhd::usrp::subdev_spec_t coerce_subdev_spec(const uhd::usrp::subdev_spec_t &); void update_subdev_spec(const std::string &tx_rx, const uhd::usrp::subdev_spec_t &); void update_time_source(const std::string &); + void set_time(const uhd::time_spec_t&); + void sync_times(void); void update_clock_source(const std::string &); void update_bandsel(const std::string& which, double freq); void update_antenna_sel(const size_t which, const std::string &ant); diff --git a/host/lib/usrp/b200/b200_io_impl.cpp b/host/lib/usrp/b200/b200_io_impl.cpp index 41b4b8a74..279901208 100644 --- a/host/lib/usrp/b200/b200_io_impl.cpp +++ b/host/lib/usrp/b200/b200_io_impl.cpp @@ -227,7 +227,8 @@ uhd::usrp::subdev_spec_t b200_impl::coerce_subdev_spec(const uhd::usrp::subdev_s // // Any other spec is probably illegal and will be caught by // validate_subdev_spec(). - if (spec.size() and (_product == B200 or _product == B205) and spec[0].sd_name == "B") { + if (spec.size() and (_product == B200 or _product == B200MINI or _product == B205MINI) and spec[0].sd_name == "B") + { spec[0].sd_name = "A"; } return spec; diff --git a/host/lib/usrp/b200/b200_regs.hpp b/host/lib/usrp/b200/b200_regs.hpp index 8f2dd03f3..e9ab81bae 100644 --- a/host/lib/usrp/b200/b200_regs.hpp +++ b/host/lib/usrp/b200/b200_regs.hpp @@ -28,7 +28,7 @@ localparam SR_CORE_SPI = 8; localparam SR_CORE_MISC = 16; localparam SR_CORE_COMPAT = 24; localparam SR_CORE_GPSDO_ST = 40; -localparam SR_CORE_PPS_SEL = 48; +localparam SR_CORE_SYNC = 48; localparam RB32_CORE_SPI = 8; localparam RB32_CORE_MISC = 16; localparam RB32_CORE_STATUS = 20; |