#!/usr/local/altera/quartus/bin/quartus_stp -t # vjuart.tcl - Virtual JTAG UART proxy for Altera devices # # Description: Create a TCP connection to listen for a telnet connection # and relay the telnet stream through the Altera VJTAG connection to a # I/O FIFO buffer. This TCL script requires Quartus STP to be installed. # Provides a simple interface to the Terasic DE0-Nano # # Copyright (C) 2014 Binary Logic (nhi.phan.logic at gmail.com). # # This file is part of the Virtual JTAG UART toolkit # # Virtual UART is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # ###################### Parameters ########################### set service_port 2323 set listen_address 0.0.0.0 set REG_OFF_WRITE 8 set REG_STATUS_INDEX 0 set REG_TXDATA_INDEX 1 set REG_RXDATA_INDEX 2 ###################### Code ################################# # Setup connection proc setup_blaster {} { global usbblaster_name global test_device foreach hardware_name [get_hardware_names] { if { [string match "USB-Blaster*" $hardware_name] } { set usbblaster_name $hardware_name } } puts "Select JTAG chain connected to $usbblaster_name."; # List all devices on the chain, and select the first device on the chain. #Devices on the JTAG chain: foreach device_name [get_device_names -hardware_name $usbblaster_name] { if { [string match "@1*" $device_name] } { set test_device $device_name } } puts "Selected device: $test_device."; } # Open device proc openport {} { global usbblaster_name global test_device open_device -hardware_name $usbblaster_name -device_name $test_device device_lock -timeout 10000 } # Close device. Just used if communication error occurs proc closeport { } { global usbblaster_name global test_device # Set IR back to 0, which is bypass mode device_virtual_ir_shift -instance_index 0 -ir_value 3 -no_captured_ir_value catch {device_unlock} catch {close_device} } # Convert decimal number to the required binary code proc dec2bin {i {width {}}} { set res {} if {$i<0} { set sign - set i [expr {abs($i)}] } else { set sign {} } while {$i>0} { set res [expr {$i%2}]$res set i [expr {$i/2}] } if {$res == {}} {set res 0} if {$width != {}} { append d [string repeat 0 $width] $res set res [string range $d [string length $res] end] } return $sign$res } # Convert a binary string to a decimal/ascii number proc bin2dec {bin} { if {$bin == 0} { return 0 } elseif {[string match -* $bin]} { set sign - set bin [string range $bin[set bin {}] 1 end] } else { set sign {} } return $sign[expr 0b$bin] } # Send data to the Altera input FIFO buffer proc send {chr} { global REG_STATUS_INDEX global REG_TXDATA_INDEX global REG_OFF_WRITE set regeff [expr $REG_TXDATA_INDEX + $REG_OFF_WRITE] device_virtual_ir_shift -instance_index 0 -ir_value $regeff -no_captured_ir_value device_virtual_dr_shift -dr_value [dec2bin $chr 8] -instance_index 0 -length 8 -no_captured_dr_value } # Read data in from the Altera output FIFO buffer proc recv {} { set result {} set rx_count 0 global REG_STATUS_INDEX global REG_RXDATA_INDEX # Check if there is anything to read while {1} { device_virtual_ir_shift -instance_index 0 -ir_value $REG_STATUS_INDEX -no_captured_ir_value set REG_STATUS [device_virtual_dr_shift -dr_value 00000000 -instance_index 0 -length 8] if {[expr $REG_STATUS & 1]} { break } set rx_count [expr $rx_count + 1] device_virtual_ir_shift -instance_index 0 -ir_value $REG_RXDATA_INDEX -no_captured_ir_value set REG_DATA [device_virtual_dr_shift -dr_value 00000000 -instance_index 0 -length 8] set dec [bin2dec $REG_DATA] append result [format %c $dec]; if {[expr $dec == 10]} { break } if {[expr $rx_count == 80]} { break } } return $result } ########## Process a connection on the port ########################### proc conn {channel_name client_address client_port} { global service_port global listen_address global wait_connection # Connect the USB Blaster openport # Configure the channel for binary fconfigure $channel_name -translation binary -buffering none -blocking false puts "Connection from $client_address" # Do the "telnet mode character", command is: # IAC WONT LINEMODE IAC WILL ECHO puts -nonewline $channel_name "\377\375\042\377\373\001" puts $channel_name "JTAG VComm, welcome $client_address on $listen_address:$service_port\r" puts "Stream byte counters:" flush $channel_name # Wait for telnet client to return 'junk' # Read and discard the junk after 100 read $channel_name 4096 variable cnt_in 0 variable cnt_out 0 while {1} { # Try to read a character from the buffer set onechar [read $channel_name 1] set numchars [string length $onechar] # Check for EOF first if {[eof $channel_name]} break # Did we receive something? if { $numchars > 0 } { # Convert the character to ascii code scan $onechar %c ascii #Transmit this recieved character send $ascii # Update the counters incr cnt_in puts -nonewline "\rin: $cnt_in, out: $cnt_out" flush stdout } # Now check data coming out from VComm if {[eof $channel_name]} break set str [recv] set len [string length $str] if {[expr $len > 0]} { puts -nonewline $channel_name $str incr cnt_out puts -nonewline "\rin: $cnt_in, out: $cnt_out" } } close $channel_name puts "\nClosed connection" closeport set wait_connection 1 } ####################### Main code ################################### global usbblaster_name global test_device global wait_connection # Find the USB Blaster setup_blaster # Start the server socket socket -server conn -myaddr $listen_address $service_port # Loop forever while {1} { # Set the exit variable to 0 set wait_connection 0 # Display welcome message puts "JTAG VComm listening on $listen_address:$service_port" # Wait for the connection to exit vwait wait_connection } ##################### End Code ########################################