Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
14 years ago

How to read USERCODE from FPGA?

How to read USERCODE from configured FPGA?

I tried to use Quartus Programmer, but there is no function, which read and display the USERCODE from running FPGA.

It surprise me, that Quartus Programmer doesn't support this simple but useful function.

Are there exist any other tools to get and display the USERCODE from running FPGA?

Martin

3 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    How to read USERCODE from configured FPGA?

    --- Quote End ---

    Using quartus_stp, you can issue JTAG commands to get this info, i.e.,

    #  -----------------------------------------------------------------#  JTAG access (open/close)#  -----------------------------------------------------------------
    #  Open the DE2 Cyclone II device using the on-board USB-Blaster.
    proc jtag_open {} {
       #  Get the list of JTAG controllers
        set hardware_names 
        
       #  Select the first JTAG controller
        set hardware_name 
        
       #  Get the list of FPGAs in the JTAG chain
        set device_names 
        
       #  Select the first FPGA
        set device_name 
        puts "\nJTAG: $hardware_name, FPGA: $device_name"
        open_device -hardware_name $hardware_name
            -device_name $device_name
    }
    #  Close the device
    proc jtag_close {} {
        close_device
    }
    #  -----------------------------------------------------------------#  JTAG instructions#  -----------------------------------------------------------------
    #  Read the JTAG ID code#   * Expected ID code = 0x020B40DD# 
    proc read_idcode {} {
        device_lock -timeout 10000
       #  Shift-IR: = IDCODE = 6
        device_ir_shift -ir_value 6 -no_captured_ir_value
        
       #  Shift-DR: read 32-bits
        set val 0x
        device_unlock
        return $val
    }
    #  Read the JTAG USERCODE code#   * If its not set, then the expected value is 0xFFFFFFFF#   * The USERCODE can be set using, eg.#      set_global_assignment -name STRATIX_JTAG_USER_CODE 12345678# 
    proc read_usercode {} {
        device_lock -timeout 10000
       #  Shift-IR: = USERCODE = 7
        device_ir_shift -ir_value 7 -no_captured_ir_value
        
       #  Shift-DR: read 32-bits
        set val 0x
        device_unlock
        return $val
    }
    

    Put the above in a file, save as say jtag.tcl, and then in quartus_stp type

    
    source jtag.tcl
    jtag_open
    read_idcode
    read_usercode
    jtag_close
    

    Easy, eh!

    Cheers,

    Dave
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Using quartus_stp, you can issue JTAG commands to get this info, i.e.,

    Hi Dave,

    thank you a lot for the code. It works well. In meantime I was successful with some similar code written in JAM. After looking to your code I have to say, that the TCL is definitively better instrument.

    But I have to say again that it really surprise me, that Quartus Programmer doesn't support this simple but very useful function. Xilinx iMPACT and Lattice ispVM supports this function.

    
    NOTE "STAPL_VERSION" "JESD71";
    NOTE "JAM_VERSION" "2.0";
    NOTE "MAX_FREQ" "10000000";
    'Declare variables for data arrays
    BOOLEAN read_data;
    BOOLEAN idcode = BIN 0110000000;
    BOOLEAN usercode = BIN 1110000000;
    BOOLEAN ones_data = HEX FFFFFFFF;
    PRINT "Get IDCODE and USERCODE.";
    PRINT "";
    'GET IDCODE
    STATE RESET;
    IRSCAN 10, idcode;
    DRSCAN 32, ones_data, CAPTURE read_data;
    PRINT "IDCODE:";
    PRINT "---- ------------------- ------------- -";
    PRINT "Rev  Device              Mfgr          1";
    PRINT "---- ------------------- ------------- -";
    PRINT
      'revision
      read_data, read_data, read_data, read_data, " ",
      'device
      read_data, read_data, read_data, read_data, " ",
      read_data, read_data, read_data, read_data, " ",
      read_data, read_data, read_data, read_data, " ",
      read_data, read_data, read_data, read_data, " ",
      'vendor
      read_data, read_data, read_data, read_data, " ",
      read_data, read_data, read_data, read_data, " ",
      read_data, read_data, read_data, " ",
      'mandatory 1
      read_data;
    PRINT "";
    STATE IDLE;
    WAIT 5 USEC, 3 CYCLES;
    'GET USERCODE
    STATE RESET;
    IRSCAN 10, usercode;
    DRSCAN 32, ones_data, CAPTURE read_data;
    PRINT "USERCODE:";
    PRINT
      read_data, read_data, read_data, read_data, " ",
      read_data, read_data, read_data, read_data, " ",
      read_data, read_data, read_data, read_data, " ",
      read_data, read_data, read_data, read_data, " ",
      read_data, read_data, read_data, read_data, " ",
      read_data, read_data, read_data, read_data, " ",
      read_data, read_data, read_data, read_data, " ",
      read_data, read_data, read_data, read_data;
    PRINT "";
    EXIT 0;
    
    Kind Regards, Martin
  • ASaar2's avatar
    ASaar2
    Icon for New Contributor rankNew Contributor

    While this is an old thread, Google led me here while I was looking for a way to read the USERCODE from an Intel FPGA. Unfortunately the TCL code above doesn't work in newer Quartus (I have 17.1 at the moment) but that was easily fixed. The builtin help of quartus_stp gives an example on how to read the ID code of an FPGA and adapting from the above code I ended up with this script which prints out the IDCODE and USERCODE:

    # List all available programming hardware, and select the USB-Blaster.
    # (Note: this example assumes only one USB-Blaster is connected.)
    puts "Programming Hardware:"
    foreach hardware_name [get_hardware_names] {
            puts $hardware_name
            if { [string match "USB-Blaster*" $hardware_name] } {
                    set usbblaster_name $hardware_name
            }
    }
    puts "\nSelect JTAG chain connected to $usbblaster_name.\n";
     
    # List all devices on the chain, and select the first device on the chain.
    puts "\nDevices on the JTAG chain:"
    foreach device_name [get_device_names -hardware_name $usbblaster_name] {
            puts $device_name
            if { [string match "@1*" $device_name] } {
                    set test_device $device_name
            }
    }
    puts "\nSelect device: $test_device.\n";
     
    # Open device
    open_device -hardware_name $usbblaster_name -device_name $test_device
     
    # Retrieve device id code.
    # IDCODE instruction value is 6; The ID code is 32 bits long.
     
    # IR and DR shift should be locked together to ensure that other applications
    # will not change the instruction register before the id code value is shifted
    # out while the instruction register is still holding the IDCODE instruction.
    device_lock -timeout 10000
    device_ir_shift -ir_value 6 -no_captured_ir_value
    puts "IDCODE: 0x[device_dr_shift -length 32 -value_in_hex]"
    device_unlock
     
    # Anssi adapted for reading USERCODE as well
    device_lock -timeout 10000
    device_ir_shift -ir_value 7 -no_captured_ir_value
    puts "USERCODE: 0x[device_dr_shift -length 32 -value_in_hex]"
    device_unlock
     
    # Close device
    close_device

    Save the script to a file, for example idcode_usercode.tcl and run the script with quartus_stp -t idcode_usercode.tcl