- initial import git-svn-id: http://moon:8086/svn/vhdl/trunk@1340 cc03376c-175c-47c8-b038-4cd826a8556b
257 lines
6.6 KiB
Tcl
257 lines
6.6 KiB
Tcl
#!/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 <http://www.gnu.org/licenses/>.
|
|
#
|
|
|
|
###################### 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 ########################################
|