Discussion:
Example code for reading and writing data via BSCAN_SPARTAN6 with urJTAG and Python
(too old to reply)
wzab
2010-08-03 19:48:24 UTC
Permalink
This post contains the updated version of the code published in news:***@wzab.nasz.dom
(posted to alt.sources with the subject "Example code for reading and writing data via BSCAN_SPARTAN3 with urJTAG and Python")
The updated version works with SPARTAN6 chips, and has been tested with the SP601 Development Kit.
The code implementing the controller for internal parallel bus is available in news:***@wzab.nasz.dom

#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.9).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `#!/bin/sh' line above, then type `sh FILE'.
#
lock_dir=_sh07772
# Made on 2010-08-03 21:38 CEST by <***@wzab>.
# Source directory was `/tmp/bscan'.
#
# Existing files will *not* be overwritten, unless `-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 3667 -rw-r--r-- bscan_cap_upd.vhd
# 2275 -rw-r--r-- bscan_top.vhd
# 724 -rw-r--r-- system.ucf
#
MD5SUM=${MD5SUM-md5sum}
f=`${MD5SUM} --version | egrep '^md5sum .*(core|text)utils'`
test -n "${f}" && md5check=true || md5check=false
${md5check} || \
echo 'Note: not verifying md5sums. Consider installing GNU coreutils.'
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
if test "$gettext_dir" = FAILED && test -f $dir/gettext \
&& ($dir/gettext --version >/dev/null 2>&1)
then
case `$dir/gettext --version 2>&1 | sed 1q` in
*GNU*) gettext_dir=$dir ;;
esac
fi
if test "$locale_dir" = FAILED && test -f $dir/shar \
&& ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
then
locale_dir=`$dir/shar --print-text-domain-dir`
fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
echo=echo
else
TEXTDOMAINDIR=$locale_dir
export TEXTDOMAINDIR
TEXTDOMAIN=sharutils
export TEXTDOMAIN
echo="$gettext_dir/gettext -s"
fi
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null
then if (echo -n test; echo 1,2,3) | grep n >/dev/null
then shar_n= shar_c='
'
else shar_n=-n shar_c= ; fi
else shar_n= shar_c='\c' ; fi
f=shar-touch.$$
st1=200112312359.59
st2=123123592001.59
st2tr=123123592001.5 # old SysV 14-char limit
st3=1231235901

if touch -am -t ${st1} ${f} >/dev/null 2>&1 && \
test ! -f ${st1} && test -f ${f}; then
shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'

elif touch -am ${st2} ${f} >/dev/null 2>&1 && \
test ! -f ${st2} && test ! -f ${st2tr} && test -f ${f}; then
shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'

elif touch -am ${st3} ${f} >/dev/null 2>&1 && \
test ! -f ${st3} && test -f ${f}; then
shar_touch='touch -am $3$4$5$6$2 "$8"'

else
shar_touch=:
echo
${echo} 'WARNING: not restoring timestamps. Consider getting and
installing GNU `touch'\'', distributed in GNU coreutils...'
echo
fi
rm -f ${st1} ${st2} ${st2tr} ${st3} ${f}
#
if test ! -d ${lock_dir} ; then :
else ${echo} "lock directory ${lock_dir} exists"
exit 1
fi
if mkdir ${lock_dir}
then ${echo} "x - created lock directory ${lock_dir}."
else ${echo} "x - failed to create lock directory ${lock_dir}."
exit 1
fi
# ============= bscan_cap_upd.vhd ==============
if test -f 'bscan_cap_upd.vhd' && test "$first_param" != -c; then
${echo} "x - SKIPPING bscan_cap_upd.vhd (file already exists)"
else
${echo} "x - extracting bscan_cap_upd.vhd (text)"
sed 's/^X//' << 'SHAR_EOF' > 'bscan_cap_upd.vhd' &&
-------------------------------------------------------------------------------
-- Title : bscan_cap_upd - sample interface to BSCAN_SPARTAN6 component
-- Project :
-------------------------------------------------------------------------------
-- File : bscan_cap_upd.vhd
-- Author : Wojciech M. Zabolotny
-- Company :
-- Created : 2009-05-20
-- Last update: 2010-08-03
-- Platform :
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description: This implementation is based on the Figure 4 in the Xilinx
-- XAPP188 note (even though it is for BSCAN_SPARTAN2)
-- http://www.xilinx.com/support/documentation/application_notes/xapp188.pdf
-- Then it has been converted for the BSCAN_SPARTAN6, using info
-- found in: http://www.xilinx.com/support/documentation/sw_manuals/xilinx11/spartan6_hdl.pdf
-------------------------------------------------------------------------------
-- Copyright (c) 2009 Wojciech M. Zabolotny (wzab<at>ise.pw.edu.pl)
-- However this is PUBLIC DOMAIN code
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2009-05-21 1.0 wzab Created
-------------------------------------------------------------------------------
--
--
X
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
library work;
X
entity bscan_cap_upd is
X generic (
X DR_WIDTH : integer := 16);
X port (
X captured_data : in std_logic_vector(DR_WIDTH-1 downto 0);
X written_data : out std_logic_vector(DR_WIDTH-1 downto 0);
X wr_strobe : out std_logic
X );
end bscan_cap_upd;
X
architecture syn of bscan_cap_upd is
X
X component BSCAN_SPARTAN6
X generic (JTAG_CHAIN : integer);
X port (CAPTURE : out std_ulogic;
X DRCK : out std_ulogic;
X RESET : out std_ulogic;
X RUNTEST : out std_ulogic;
X SEL : out std_ulogic;
X SHIFT : out std_ulogic;
X TCK : out std_ulogic;
X TDI : out std_ulogic;
X TMS : out std_ulogic;
X UPDATE : out std_ulogic;
X TDO : in std_ulogic);
X end component;
X signal jt_shift, jt_tck, jt_update, jt_tdi, jt_tdo, jt_tms,
X jt_runtest, jt_drck,
X jt_capture, jt_sel, jt_reset, jt1, jt2, jt3 : std_ulogic := '0';
X signal dr : std_logic_vector(DR_WIDTH-1 downto 0);
X
X
begin
X
X BSCAN_SPARTAN6_1 : BSCAN_SPARTAN6
X generic map ( JTAG_CHAIN=>1)
X port map (
X CAPTURE => jt_CAPTURE,
X DRCK => jt_DRCK,
X RESET => jt_RESET,
X RUNTEST => jt_RUNTEST,
X SEL => jt_SEL,
X SHIFT => jt_SHIFT,
X TDI => jt_TDI,
X TCK => jt_TCK,
X TMS => jt_TMS,
X UPDATE => jt_UPDATE,
X TDO => jt_TDO);
X
X -- Load and shift data
X pjtag : process (jt_drck, jt_reset)
X begin -- process
X if jt_reset = '1' then
X dr <= (others => '0');
X elsif jt_drck'event and jt_drck = '1' then
X if jt_shift = '0' then
X dr <= captured_data;
X else
X dr(DR_WIDTH-1) <= jt_tdi;
X for i in 0 to DR_WIDTH-2 loop
X dr(i) <= dr(i+1);
X end loop; -- i
X end if;
X end if; -- jt_reset & jt_drck1
X end process pjtag;
X
X jt_TDO <= dr(0);
X
X pupd : process(jt_reset, jt_update)
X begin -- process
X if jt_reset = '1' then
X written_data <= (others => '1');
X elsif jt_update'event and jt_update = '1' then
X if jt_sel = '1' then
X written_data <= dr;
X end if;
X end if;
X end process pupd;
X
X wr_strobe <= jt_update and jt_sel;
X
end syn;
SHAR_EOF
(set 20 10 08 03 21 36 15 'bscan_cap_upd.vhd'
eval "${shar_touch}") && \
chmod 0644 'bscan_cap_upd.vhd'
if test $? -ne 0
then ${echo} "restore of bscan_cap_upd.vhd failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'bscan_cap_upd.vhd': 'MD5 check failed'
) << \SHAR_EOF
e7341d3769914ce63a01d5e94de09d94 bscan_cap_upd.vhd
SHAR_EOF
else
test `LC_ALL=C wc -c < 'bscan_cap_upd.vhd'` -ne 3667 && \
${echo} "restoration warning: size of 'bscan_cap_upd.vhd' is not 3667"
fi
fi
# ============= bscan_top.vhd ==============
if test -f 'bscan_top.vhd' && test "$first_param" != -c; then
${echo} "x - SKIPPING bscan_top.vhd (file already exists)"
else
${echo} "x - extracting bscan_top.vhd (text)"
sed 's/^X//' << 'SHAR_EOF' > 'bscan_top.vhd' &&
-------------------------------------------------------------------------------
-- Title : Demo code for SP601 - communication via JTAG with the user core
-- Project :
-------------------------------------------------------------------------------
-- File : bscan_top.vhd
-- Author : Wojciech M. Zabolotny <***@ise.pw.edu.pl>
-- Company :
-- Created : 2007-12-31
-- Last update: 2010-08-03
-- Platform :
-- Standard : VHDL
-------------------------------------------------------------------------------
-- Description:
-- This code shows, how it is possible to communicate with the user's core
-- via JTAG interface (via BSCAN_SPARTAN6 component)
-------------------------------------------------------------------------------
-- Copyright (c) 2010
-- This is public domain code!!!
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2007-12-31 1.0 wzab Created
-------------------------------------------------------------------------------
X
X
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
X
entity lcd_test is
X
X port (
X led : out std_logic_vector(3 downto 0);
X switches : in std_logic_vector(3 downto 0);
X flash_oen : out std_logic;
X flash_wen : out std_logic;
X flash_cen : out std_logic);
X
end lcd_test;
X
architecture beh of lcd_test is
X
X component bscan_cap_upd
X generic (
X DR_WIDTH : integer);
X port (
X captured_data : in std_logic_vector(DR_WIDTH-1 downto 0);
X written_data : out std_logic_vector(DR_WIDTH-1 downto 0);
X wr_strobe : out std_logic);
X end component;
X
X signal captured_data : std_logic_vector(7 downto 0);
X signal written_data : std_logic_vector(7 downto 0);
X signal wr_strobe : std_logic;
X
begin -- beh
X
X flash_cen <= '1';
X flash_wen <= '1';
X flash_oen <= '1';
X
X captured_data(3 downto 0) <= switches;
X captured_data(7 downto 4) <= (others => '0');
X led <= written_data(3 downto 0);
X
X bscan_cap_upd_1 : bscan_cap_upd
X generic map (
X DR_WIDTH => 8)
X port map (
X captured_data => captured_data,
X written_data => written_data,
X wr_strobe => wr_strobe);
X
end beh;
SHAR_EOF
(set 20 10 08 03 21 37 57 'bscan_top.vhd'
eval "${shar_touch}") && \
chmod 0644 'bscan_top.vhd'
if test $? -ne 0
then ${echo} "restore of bscan_top.vhd failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'bscan_top.vhd': 'MD5 check failed'
) << \SHAR_EOF
f7f98f22704d402f81bb5ee993c5bb00 bscan_top.vhd
SHAR_EOF
else
test `LC_ALL=C wc -c < 'bscan_top.vhd'` -ne 2275 && \
${echo} "restoration warning: size of 'bscan_top.vhd' is not 2275"
fi
fi
# ============= system.ucf ==============
if test -f 'system.ucf' && test "$first_param" != -c; then
${echo} "x - SKIPPING system.ucf (file already exists)"
else
${echo} "x - extracting system.ucf (text)"
sed 's/^X//' << 'SHAR_EOF' > 'system.ucf' &&
X
Net led<0> LOC = E13 | IOSTANDARD = LVCMOS25;
Net led<1> LOC = C14 | IOSTANDARD = LVCMOS25;
Net led<2> LOC = C4 | IOSTANDARD = LVCMOS25;
Net led<3> LOC = A4 | IOSTANDARD = LVCMOS25;
X
Net switches<0> LOC = P4 | IOSTANDARD = LVCMOS18;
Net switches<1> LOC = F6 | IOSTANDARD = LVCMOS18;
Net switches<2> LOC = E4 | IOSTANDARD = LVCMOS18;
Net switches<3> LOC = F5 | IOSTANDARD = LVCMOS18;
X
X
Net flash_wen LOC=M16;
Net flash_wen SLEW = SLOW;
Net flash_wen DRIVE = 4;
Net flash_wen IOSTANDARD = LVCMOS25;
X
Net flash_oen LOC=L18;
Net flash_oen SLEW = SLOW;
Net flash_oen DRIVE = 4;
Net flash_oen IOSTANDARD = LVCMOS25;
X
Net flash_cen LOC=L17;
Net flash_cen SLEW = SLOW;
Net flash_cen DRIVE = 4;
Net flash_cen IOSTANDARD = LVCMOS25;
SHAR_EOF
(set 20 10 08 03 21 32 24 'system.ucf'
eval "${shar_touch}") && \
chmod 0644 'system.ucf'
if test $? -ne 0
then ${echo} "restore of system.ucf failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'system.ucf': 'MD5 check failed'
) << \SHAR_EOF
4a13afa1a156e63e415d334419f49fc4 system.ucf
SHAR_EOF
else
test `LC_ALL=C wc -c < 'system.ucf'` -ne 724 && \
${echo} "restoration warning: size of 'system.ucf' is not 724"
fi
fi
if rm -fr ${lock_dir}
then ${echo} "x - removed lock directory ${lock_dir}."
else ${echo} "x - failed to remove lock directory ${lock_dir}."
exit 1
fi
exit 0
Wojciech M. Zabolotny
2010-08-03 19:56:50 UTC
Permalink
The previous post didn't contain the Python code adjusted for SP601.

#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.9).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `#!/bin/sh' line above, then type `sh FILE'.
#
lock_dir=_sh08061
# Made on 2010-08-03 21:54 CEST by <***@wzab>.
# Source directory was `/home/xl/ise_projects/Spartan6/jtag_bus1/python'.
#
# Existing files will *not* be overwritten, unless `-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 1874 -rw-r--r-- bscan_test.py
#
MD5SUM=${MD5SUM-md5sum}
f=`${MD5SUM} --version | egrep '^md5sum .*(core|text)utils'`
test -n "${f}" && md5check=true || md5check=false
${md5check} || \
echo 'Note: not verifying md5sums. Consider installing GNU coreutils.'
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
if test "$gettext_dir" = FAILED && test -f $dir/gettext \
&& ($dir/gettext --version >/dev/null 2>&1)
then
case `$dir/gettext --version 2>&1 | sed 1q` in
*GNU*) gettext_dir=$dir ;;
esac
fi
if test "$locale_dir" = FAILED && test -f $dir/shar \
&& ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
then
locale_dir=`$dir/shar --print-text-domain-dir`
fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
echo=echo
else
TEXTDOMAINDIR=$locale_dir
export TEXTDOMAINDIR
TEXTDOMAIN=sharutils
export TEXTDOMAIN
echo="$gettext_dir/gettext -s"
fi
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null
then if (echo -n test; echo 1,2,3) | grep n >/dev/null
then shar_n= shar_c='
'
else shar_n=-n shar_c= ; fi
else shar_n= shar_c='\c' ; fi
f=shar-touch.$$
st1=200112312359.59
st2=123123592001.59
st2tr=123123592001.5 # old SysV 14-char limit
st3=1231235901

if touch -am -t ${st1} ${f} >/dev/null 2>&1 && \
test ! -f ${st1} && test -f ${f}; then
shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'

elif touch -am ${st2} ${f} >/dev/null 2>&1 && \
test ! -f ${st2} && test ! -f ${st2tr} && test -f ${f}; then
shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'

elif touch -am ${st3} ${f} >/dev/null 2>&1 && \
test ! -f ${st3} && test -f ${f}; then
shar_touch='touch -am $3$4$5$6$2 "$8"'

else
shar_touch=:
echo
${echo} 'WARNING: not restoring timestamps. Consider getting and
installing GNU `touch'\'', distributed in GNU coreutils...'
echo
fi
rm -f ${st1} ${st2} ${st2tr} ${st3} ${f}
#
if test ! -d ${lock_dir} ; then :
else ${echo} "lock directory ${lock_dir} exists"
exit 1
fi
if mkdir ${lock_dir}
then ${echo} "x - created lock directory ${lock_dir}."
else ${echo} "x - failed to create lock directory ${lock_dir}."
exit 1
fi
# ============= bscan_test.py ==============
if test -f 'bscan_test.py' && test "$first_param" != -c; then
${echo} "x - SKIPPING bscan_test.py (file already exists)"
else
${echo} "x - extracting bscan_test.py (text)"
sed 's/^X//' << 'SHAR_EOF' > 'bscan_test.py' &&
#!/usr/bin/python
import pexpect
import re
import time
import os
class urjtag:
X def __init__(self):
X self.p=pexpect.spawn("urjtag")
X self.p.expect("jtag>")
X self.af=re.compile("(.*\r\n)*")
X def cmd(self,line):
X self.p.sendline(line)
X self.p.expect_exact("jtag>")
X if self.p.before.find("Error:")>=0:
X #res=-1
X raise("error")
X elif self.p.before.find("Unknown")>=0 or \
X self.p.before.find("unknown")>=0:
X #res=-2
X raise ("unknown command or syntax error")
X return self.p.before
X def send_dr(self,dr_as_str):
X w=u.cmd("dr "+dr_as_str+":: shift dr :: dr")
X #print w
X g=self.af.search(w)
X return int(g.group(1).strip(), base=2)
X #int(, base=2)
X
X
u=urjtag()
u.cmd("cable xpc_ext")
s=u.cmd("detect")
#Here we parse the output of the "detect" command,
#Building the list of the parts
parts=[]
finder=re.compile(r'.*Part\((?P<num>.*?)\):\s*(?P<name>\S*)', re.M)
start=0
while True:
X rs=finder.search(s,start)
X if not rs:
X break
X # We have found a new part, add it to the list of parts
X parts.append((rs.group('num'),rs.group('name')))
X start=rs.span()[1]
# OK, so we set all the parts except the xc6slx16-csg324 in the BYPASS
# mode
for p in parts:
X if p[1]=="xc6slx16-csg324":
X u.cmd("part "+p[0])
X u.cmd("register UR 8")
X # In fact 17 was sufficient, but either urJTAG or XPCU didn't work correctly
X # for instruction register length equal to 17!
X u.cmd("instruction USER1 000010 UR")
X u.cmd("instruction USER1")
X u.cmd("shift ir")
X print "found!!!"
X else:
X u.cmd("part "+p[0])
X u.cmd("instruction BYPASS")
X u.cmd("shift ir")
X
LEDS="00000001"
while True:
X tt= u.send_dr(LEDS)
X print(hex(tt))
X LEDS=(LEDS+"0")
X if LEDS[0]=="1":
X LEDS="00000001"
X else:
X LEDS=LEDS[1:]
X
X
SHAR_EOF
(set 20 10 08 03 16 55 19 'bscan_test.py'
eval "${shar_touch}") && \
chmod 0644 'bscan_test.py'
if test $? -ne 0
then ${echo} "restore of bscan_test.py failed"
fi
if ${md5check}
then (
${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'bscan_test.py': 'MD5 check failed'
) << \SHAR_EOF
bc69399b4e02704b0176f331a6d66054 bscan_test.py
SHAR_EOF
else
test `LC_ALL=C wc -c < 'bscan_test.py'` -ne 1874 && \
${echo} "restoration warning: size of 'bscan_test.py' is not 1874"
fi
fi
if rm -fr ${lock_dir}
then ${echo} "x - removed lock directory ${lock_dir}."
else ${echo} "x - failed to remove lock directory ${lock_dir}."
exit 1
fi
exit 0
Wojciech M. Zabolotny
2015-05-17 14:48:46 UTC
Permalink
This post might be inappropriate. Click to display it.
w***@gmail.com
2018-12-20 22:54:37 UTC
Permalink
Below is the simple Tcl code that provides communication with the jtag_bus_ctl_3.vhd via Tcl script in Vivado instead of Python & UrJtag:

=======================================================
# Script prepared by Wojciech M. Zabolotny (wzab<at>ise.pw.edu.pl)
# to drive the jtag_bus_ctl.vhd core (published in the
# https://groups.google.com/d/msg/alt.sources/Rh5yEuF2YGE/rAzJMOFDNz8J
# thread on alt.sources usenet group
#


# Set two constants below according to the address and data width
# in the instantiated controller
set d_width 8
set a_width 8

set ad_width [ expr max($d_width, $a_width)]
set s_width [ expr $ad_width + 2 ]
set a_mask [ expr ( 1 << $a_width) - 1 ]
set d_mask [ expr ( 1 << $d_width) - 1 ]

proc bus_init { } {
close_hw
catch open_hw
catch {connect_hw_server -url localhost:3121}
# You may need to adjust the lines below!
set JTAG */xilinx_tcf/Xilinx/*
current_hw_target [get_hw_targets $JTAG]
open_hw_target -jtag_mode 1
get_hw_devices
run_state_hw_jtag reset
run_state_hw_jtag idle
# The length of the shift should correspond to the length of the instruction register of your FPGA
# The shifted value should correspond to the USER command, that selects
# your BSCANE2 as the data register
scan_ir_hw_jtag 6 -tdi 02
}

proc bus_write { address value } {
global ad_width
global s_width
global a_mask
global d_mask
set shval [ expr ( 3 << $ad_width ) | ( $address & $a_mask ) ]
scan_dr_hw_jtag $s_width -tdi [format %x $shval]
set shval [ expr ( 0 << $ad_width ) | ( $value & $d_mask ) ]
scan_dr_hw_jtag $s_width -tdi [format %x $shval]
}

proc bus_read { address } {
global ad_width
global s_width
global a_mask
global d_mask
set shval [ expr ( 2 << $ad_width ) | ( $address & $a_mask ) ]
scan_dr_hw_jtag $s_width -tdi [format %x $shval]
set shval [ scan_dr_hw_jtag $s_width -tdi 0x0 ]
set shval [expr 0x$shval & $d_mask ]
return $shval
}
=======================================================
w***@gmail.com
2018-12-20 23:49:35 UTC
Permalink
This post might be inappropriate. Click to display it.
Loading...