• 0
Pavel_47

Using Adept SDK to handle JTAG on ZC706 board: problems.

Question

Hello,

Here is extract of JTAG sequence for reading status register of Zynq-7000 (picked from UG470 - 7-Series configuration guide):

ug470-status-register-readback-sequence.

Here is fragment of my code for executing:

  • 1st step (until Shift the first five bits ...)
  • the beginning of 2nd step (just Shift CFG_IN instruction)

Declaration part:

HIF hif;
char jtag_version[20];
BYTE move_Shift_IR[] = { 0xDF, 0x00 };
BYTE shft_CFG_IN[] = {0x11, 0x08, 0x00};

Execution part:

		private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
			DjtgGetVersion(jtag_version);
			if (!DmgrOpen(&hif, "JtagSmt2")) {
				printf("Error: Could not open device. Check device name\n");
				ErrorExit();
			}
			if (!DjtgEnable(hif)) {
				printf("Error: DjtgEnable failed\n");
				ErrorExit();
			}

			// Put JTAG in Shift-IR state
			if (!DjtgPutTmsBits(hif, fTrue, move_Shift_IR, NULL, 10, fFalse))
			{
				printf("DjtgPutTmsBits failed\n");
				ErrorExit();
			}

			if (!DjtgPutTdiBits(hif, fTrue, shft_CFG_IN, NULL, 6, fFalse)) {
				printf("DjtgPutTdiBits failed\n");
				ErrorExit();
			}

I control execution of the code with LeCroy logic analyzer and when I look at waveforms I feel a little embarrassed: 1st step is visible while 2nd - not at all.

Le-Croy-register-readback-sequence-begin

Any comments ?

Thanks.

Pavel.

ug470_status_register_readback_sequence.jpg

Share this post


Link to post
Share on other sites

7 answers to this question

Recommended Posts

  • 0

Hi Jon,

Thank you for feedback.

Have you looked through the PDF documents in the Adept SDK folder?

Sure, I did it ... and examined two examples dedicated to JTAG control.

Here the problem does not concern a particular development board (ZC706 or one else).

Xilinx development boards let's say medium range (probably also "high-end" boards) use Digilent JTAG-SMTx modules as principal programming interface (at least ZC706 (Zynq-7045) and KCU105 (Kintex Ultrascale) that I'm working with, use JTAG-SMTx).

So, the problem concerns rather manipulating of the JTAG-SMTx using Adept SDK.

As I showed in my previous mail, the 1st function call (DjtgPutTmsBits) produces activity on JTAG lines (TCK and TMS) while 2nd function call (DjtgPutTdiBits) has no any effect.

And yet my control sequence is done in full compliance with table 6-2 of the example taken from the Xilinx Series 7 configuration guide.

So, either the sequence from table 6-2 is erroneous, either I misinterpreted it with Adept SDK and 1st function call (DjtgPutTmsBits) didn't put JTAG TAP controller in Shift-IR state, the state where CFG_IN instruction is executed.

As you can state from waveforms in LeCroy Logic Studio software (I connected the probes of LeCroy logic analyzer directlly to the JTAG ports of  JTAG-SMTx) the DjtgPutTdiBits call (2nd function call) has no any effect ... even on TCK line I don't see any pulse.

Sincerely,

Pavel.

Share this post


Link to post
Share on other sites
  • 0

Hi @Pavel_47,

I'm curious as to why you chose your implementation of the DjtgPutTdiBits that you kept the TMS pin at a high state (second parameter in the function) when the table 6.2 states you need to keep the TMS line in a low state and why you are attempting to shift in 6 bits when the beginning of the second step only requires 5 bits which seem to be 00101. Based on your declared shft_CFG_IN array, you also seem to be wanting to shift in 3 bytes worth of data rather than the total of 10 bits for the second step.

To be fair, I do not know why you do not see anything on the TCK line; I do not know if that is due to how JTAG expects things to be done or if it is because you have extra bits left over in the byte that are not being shifted in.

Based on the table you referenced and the DJTG Programmer's Reference Manual, I believe (I have not tested this for myself) you would want the following for the second step:

//following the coding style provided
//Declarations, though these don't need to be arrays
BYTE shft_CFG_IN_part1[] = {0x05}; //corresponds to the 00101
BYTE shft_CFG_IN_part2_and_part3[] = {0x00}; //single 0 and two don't cares
BYTE shft_CFG_IN_part4 = {0x00}; //two don't cares

//Executions
//first 5 bits, with TMS held low
if (!DjtgPutTdiBits(hif, fFalse, shft_CFG_IN, NULL, 5, fFalse)) {
				printf("DjtgPutTdiBits part1 failed\n");
				ErrorExit();
			}
//second part and third part, with TMS held high
if (!DjtgPutTdiBits(hif, fTrue, shft_CFG_IN, NULL, 3, fFalse)) {
				printf("DjtgPutTdiBits part2 and 3 failed\n");
				ErrorExit();
			}
//fourth part, with TMS held low
if (!DjtgPutTdiBits(hif, fFalse, shft_CFG_IN, NULL, 2, fFalse)) {
				printf("DjtgPutTdiBits part4 failed\n");
				ErrorExit();
			}

Thanks,
JColvin

Share this post


Link to post
Share on other sites
  • 0
On 12/4/2018 at 4:38 PM, Pavel_47 said:

Any comments ?
 

Hi,

just had a thought on this: Is it possible that the 2nd command is simply off-screen?

The clock is 10 MHz so this is clearly generated on the board on a 100 ns grid. But I'd expect that different commands in the SW will go each in its own USB (micro)frame, putting them on a 125000 ns grid or slower.

The reference manual mentions "selectable clock frequency" - I'd simply try to run this at 8 kHz instead of 10 MHz.

Share this post


Link to post
Share on other sites
  • 0
6 hours ago, xc6lx45 said:

Hi,

just had a thought on this: Is it possible that the 2nd command is simply off-screen?

The clock is 10 MHz so this is clearly generated on the board on a 100 ns grid. But I'd expect that different commands in the SW will go each in its own USB (micro)frame, putting them on a 125000 ns grid or slower.

The reference manual mentions "selectable clock frequency" - I'd simply try to run this at 8 kHz instead of 10 MHz.

Yes, it was exactly the case !

The time laps between 2 consequent function calls are so long (why ?) that the 2nd call occurs outside of the time scope, covered by LeCroy software.

I've modified a little my code in order to follow step-by-step the JTAG sequence:

jtag-exploring-visual-studio-form.jpg

So, executing each instruction separately, I can control what is going on at JTAG lines.

Share this post


Link to post
Share on other sites
  • 0
10 hours ago, JColvin said:

Hi @Pavel_47,

I'm curious as to why you chose your implementation of the DjtgPutTdiBits that you kept the TMS pin at a high state (second parameter in the function) when the table 6.2 states you need to keep the TMS line in a low state and why you are attempting to shift in 6 bits when the beginning of the second step only requires 5 bits which seem to be 00101. Based on your declared shft_CFG_IN array, you also seem to be wanting to shift in 3 bytes worth of data rather than the total of 10 bits for the second step.

To be fair, I do not know why you do not see anything on the TCK line; I do not know if that is due to how JTAG expects things to be done or if it is because you have extra bits left over in the byte that are not being shifted in.

Based on the table you referenced and the DJTG Programmer's Reference Manual, I believe (I have not tested this for myself) you would want the following for the second step:

Thanks,
JColvin

Thanks JColvin,

Yes, you were right - I was wrong trying to pass CFG_IN instruction that way. Since my code has undergone many changes. Here how it looks now:

Declaration part:

HIF hif;
char jtag_version[20];
BYTE reset_JTAG_tms[] = { 0x1F };
BYTE move_Shift_IR_tms[] = { 0x0C };
BYTE shift_IR_tmstdi[] = { 0x11, 0x08 };
BYTE move_Shift_DR_tms[] = { 0x03 };
BYTE shift_Packets[] = { 0x55, 0x99, 0xAA, 0x66, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x07, 0x80, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00 };
BYTE shift_Packets_last[] = { 0x00, 0x80 };
BYTE move_shift_IR1[] = { 0x07 };
BYTE shift_IR1[] = { 0x10, 0x08 };
BYTE shift_zeros[] = { 0x00, 0x00, 0x00, 0x00 };
BYTE recv_buff[4];

Execution part:

	private: System::Void btn_Reset_Click(System::Object^  sender, System::EventArgs^  e) {
		DjtgGetVersion(jtag_version);
		if (!DmgrOpen(&hif, "JtagSmt2")) {
			lbl_error->Text = "Error: Could not open device. Check device name";
		}

		if (!DjtgEnable(hif)) {
			lbl_error->Text = "Error: DjtgEnable failed";
		}

		// Put JTAG in TLR state
		if (!DjtgPutTmsBits(hif, fFalse, reset_JTAG_tms, NULL, 5, fFalse))
		{
			lbl_error->Text = "JTAG reset failed";
		}
	}

	private: System::Void btn_Clear_Click(System::Object^  sender, System::EventArgs^  e) {
		lbl_error->Text = "";
	}
	private: System::Void btn_GetPortProperties_Click(System::Object^  sender, System::EventArgs^  e) {
		DWORD properties = 0;
		if (!DjtgGetPortProperties(hif, 0, &properties)) {
			lbl_error->Text = "ERROR: failed to get JTAG port 0 properties, erc = " + DmgrGetLastError();
		}
		lbl_GetPortProperties->Text = properties.ToString();
	}

	private: System::Void btn_MoveShiftIR_Click(System::Object^  sender, System::EventArgs^  e) {
		if (!DjtgPutTmsBits(hif, fFalse, move_Shift_IR_tms, NULL, 5, fFalse))
		{
			lbl_error->Text = "moving to Shift-IR failed";
		}
	}
	
	private: System::Void btn_ShiftIR_Click(System::Object^  sender, System::EventArgs^  e) {
		if (!DjtgPutTmsTdiBits(hif, shift_IR_tmstdi, NULL, 6, fFalse)) {
			lbl_error->Text = "Shifing IR failed";
		}
	}

	private: System::Void btn_MoveShiftDR_Click(System::Object^  sender, System::EventArgs^  e) {
		if (!DjtgPutTmsBits(hif, fFalse, move_Shift_DR_tms, NULL, 4, fFalse))
		{
			lbl_error->Text = "moving to Shift-DR failed";
		}
	}

	private: System::Void btn_ShiftDR_click(System::Object^  sender, System::EventArgs^  e) {
		if (!DjtgPutTdiBits(hif, fFalse, shift_Packets, NULL, 152, fFalse))
		{
			lbl_error->Text = "Shifting DR failed";
		}
	}

	private: System::Void btn_ShiftDR_last_Click(System::Object^  sender, System::EventArgs^  e) {
		if (!DjtgPutTmsTdiBits(hif, shift_Packets_last, NULL, 8, fFalse)) {
			lbl_error->Text = "Shifing DR last failed";
		}
	}

	private: System::Void btn_ShiftIR1_Click(System::Object^  sender, System::EventArgs^  e) {
		//move_shift_IR1
		if (!DjtgPutTmsBits(hif, fFalse, move_shift_IR1, NULL, 5, fFalse))
		{
			lbl_error->Text = "moving to Shift-IR failed";
		}
	}

	private: System::Void btn_ShiftIR1_Click_1(System::Object^  sender, System::EventArgs^  e) {
		if (!DjtgPutTmsTdiBits(hif, shift_IR1, NULL, 6, fFalse)) {
			lbl_error->Text = "Shifing IR failed";
		}
	}

	private: System::Void btn_GetStatReg_Click(System::Object^  sender, System::EventArgs^  e) {
		if (!DjtgPutTdiBits(hif, fFalse, shift_zeros, recv_buff, 32, fFalse))
		{
			lbl_error->Text = "Shifting DR failed";
		}
		else {
			lbl_error->Text = recv_buff[3].ToString() + recv_buff[2].ToString() + recv_buff[1].ToString() + recv_buff[0].ToString();
			lbl_Byte0_val->Text = recv_buff[0].ToString();
			lbl_Byte1_val->Text = recv_buff[1].ToString();
			lbl_Byte2_val->Text = recv_buff[2].ToString();
			lbl_Byte3_val->Text = recv_buff[3].ToString();
		}
	}

As you can state I used DjtgPutTmsTdiBits function to pass CFG_IN instruction (because it affects both TMS and TDI)

I can control executing of the each instruction separately using LeCroy software.

According to my observation the ensemble of these sequences corresponds to the "golden sequence" that I picked form executing fpga -config-status instruction in Xilinx SDK that is supposed to do the same thing. Despite the fact that both sequences (picked from execution of my code and that, picked from execution of fpga -config-status), the result is not the same: I display the content of the FPGA status register in lbl_Byte0_val ... lbl_Byte3_val windows form controls ... and can state that this value (unfortunately) is quite different from that, obtained from fpga -config-status.

Sincerely,

Pavel.

Share this post


Link to post
Share on other sites
  • 0

Hi,

another thing just came to mind: You're dealing with a Zynq, there are two devices in the JTAG chain (the ARM and the FPGA).

What I mean is, send 0xFFFFFFFF... to IR (repetitions of standardized BYPASS opcode 6'b111111), then send 0x01 to DR.

For a single device the response is 0x02 (one device => one register delayed). For Zynq it's 0x04 (two devices).

Edited by xc6lx45
typo

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now