久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

標(biāo)題: 虛擬JTAG工具在FPGA調(diào)試中的應(yīng)用 [打印本頁]

作者: 51黑fan    時間: 2016-1-31 04:11
標(biāo)題: 虛擬JTAG工具在FPGA調(diào)試中的應(yīng)用
本帖最后由 51黑fan 于 2016-1-31 04:16 編輯

                  最近學(xué)習(xí)了Altera的Virtual JTAG工具的使用。下面是我的使用心得。



    Altera在Quartus II 6.0中加入了一個sld_virtual_jtag 參數(shù)化宏單元模塊,并提供了相應(yīng)的Tcl程序包。有了這套工具,使用sld_virtual_jtag 和相應(yīng)的Tcl命令,我們就可以構(gòu)建自己的虛擬JTAG鏈路,并進(jìn)行自定義的JTAG調(diào)試了。

一、 相關(guān)文件

    后面的鏈接是Quartus幫助文件中的內(nèi)容,前兩個是我從Help里拷出來用Word保存的html文件,由于里面的一些鏈接指向本地文件,會被當(dāng)作危險代碼,不理就是了,不是病毒。


二、 Virtual JTAG要點解析

    澄清一個概念:所謂虛擬JTAG,是Altera用PLD上的硬件JTAG電路和可編程邏輯資源搭建的一個IP core。這個IP core實現(xiàn)了JTAG接口電路的功能,但本身不是硬件JTAG電路的一部分,是用可編程邏輯“虛擬”出來的。

    這個IP core有兩個接口:一個接口在布局布線時連接到硬件JTAG電路上,用戶不可見;一個接口由用戶通過電路圖或者HDL例化到代碼中,并通過這個接口自定義JTAG操作。

    這個IP core的功能 = JTAG信號hub + JTAG TAP控制器 + IR/DR IO。

    用戶看到的是虛擬JTAG電路對內(nèi)的接口,看不到硬件JTAG電路接口;并且這個接口是從JTAG TAP控制器引出的,信號方向和大家通常從外部對JTAG電路的理解不一樣,所以容易引起混淆,理解上會有一定的困難。

    用戶看到(可以利用)的接口有四組:




    理解虛擬JTAG概念的關(guān)鍵有以下兩點:


    理解了這些概念,看懂用戶指南應(yīng)該不成問題了。然后再看示例程序的verilog代碼。

    我的一個空想:如果Altera能夠把用戶不可見的硬件JTAG電路接口開放出來(用戶可見),那么用戶就可以把這個接口上的標(biāo)準(zhǔn)JTAG接口連接到PLD的引腳上,再把這組引腳連接到外部JTAG電路上,那么這個IP core就不再是“虛擬”的了。


三、 Tcl命令的使用。

    ::quartus::jtag Tcl命令包中的各條命令都有英文注釋,這里就不挨個翻譯了。

    下面,把用戶指南里給出的第一個例子逐句分析一下,后面還會給出一個模板。

    示例如下。其中只給::quartus::jtag Tcl命令包中的命令加上了綠色,其余簡單的Tcl命令可以按照E文的意義理解,稍微復(fù)雜一些的Tcl命令可以參考相關(guān)書籍。為了區(qū)別原注釋,我的注釋一概用紅色標(biāo)出。


#### Script begins ######################################################

set loop 3

## 檢測下載電纜,從命令行輸出檢測到的下載電纜名稱。原示例只檢測USB下載線,我給改了。 ##

# get hardware names : get download cable name
foreach hardware_name [get_hardware_names] {
    puts "\n$hardware_name"
    if { [string match "ByteBlasterMV*" $hardware_name] } {
        set byteblaster_name $hardware_name
    }
}
puts "\nSelect JTAG chain connected to $byteblaster_name.\n";


## 檢測下載電纜對應(yīng)的jtag鏈路,從命令行輸出檢測到的器件名稱。并選中第一個作為操作對象。##


# 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 $byteblaster_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 $byteblaster_name -device_name $test_device


## 獲得器件的jtag編號。需要先發(fā)送jtag命令--獲取ID,命令值是“6”。然后讀取jtag數(shù)據(jù),得到32位的ID值。##

## 由于該步驟需要兩個操作,這兩個操作之間不能插入其他操作,所以需要lock一下。##


# 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               ## 發(fā)送jtag命令 6。注意:這里的jtag是真實的jtag ##
puts "IDCODE: 0x[device_dr_shift -length 32 -value_in_hex]"     ## 獲取jtag數(shù)據(jù) ##
device_unlock

## real jtag operation completed ##

## 以下是virtual jtag的操作 ##


# SAMPLE instruction samples a 8-bit bus; the captured value shows the number of sample performed.
# FEED instruction supplies a 8-bit value to the logic connected to this instance.
# Both data registers corresponding to the IR are 8 bit wide.

## 循環(huán)采樣數(shù)據(jù)部分 ##

# Send SAMPLE instruction to IR, read captured IR for the sampling number.
# Capture the DR register for the current sampled value.

## 設(shè)置循環(huán)參數(shù) ##
set run_script 0
while {$run_script != $loop} {
    set run_script [expr $run_script +1]
    set counter1 0
    set counter2 1

    ## 獲取采樣數(shù)據(jù) ##

    device_lock -timeout 10000
    while {$counter1!=$counter2} {

        device_virtual_ir_shift -instance_index 0 -ir_value 1                               ## 發(fā)送virtual jtag命令 1 ##
        set counter1 [device_virtual_dr_shift -instance_index 0 -length 4 -value_in_hex]    ## 獲取virtual jtag數(shù)據(jù) ##

        device_virtual_ir_shift -instance_index 1 -ir_value 1                               ## 發(fā)送virtual jtag命令 1 ##
        set counter2 [device_virtual_dr_shift -instance_index 1 -length 4 -value_in_hex]    ## 獲取virtual jtag數(shù)據(jù) ##

        puts "Value of {counter2,counter1} is <$counter2,$counter1>"

        ## 設(shè)置延時參數(shù) ##

        set delay 0
        while {$delay != 120000} {
            set delay [expr $delay+1]
        }
        puts ""
    }

    device_unlock

##  交互輸入,設(shè)定FPGA計數(shù)器初值部分 ##


## instead of stopping at the equal value, force a value of supplied by the user in both  counters and then end.
# Send FEED instruction to IR, read a two-digit hex string from the console,
# then send the new value to the DR register.
    puts "\nType in a digit in hexadecimal to update the contents of the counters:"
    gets stdin update_value
    set update_value2 [expr $update_value+1]


    device_lock -timeout 10000
    device_virtual_ir_shift -instance_index 0 -ir_value 2 -no_captured_ir_value ## 發(fā)送virtual jtag命令 2 ##
    device_virtual_dr_shift -instance_index 0  -length 4 -dr_value $update_value -value_in_hex -no_captured_dr_value ## 獲取virtual jtag數(shù)據(jù) ##
    device_virtual_ir_shift -instance_index 1 -ir_value 2 -no_captured_ir_value ## 發(fā)送virtual jtag命令 2 ##
    device_virtual_dr_shift -instance_index 1  -length 4 -dr_value $update_value2 -value_in_hex -no_captured_dr_value ## 獲取virtual jtag數(shù)據(jù) ##
    device_unlock


}
# Close device
close_device

    如果要讀懂上述代碼,建議按照用戶指南中的步驟設(shè)置好工程,記得一定要把引腳按照自己電路板的情況分配上(可以不用LED)。先把## real jtag operation completed ##之前的代碼運行一下,看看有什么反應(yīng)。如果反應(yīng)很好的話,那么祝賀你,你已經(jīng)克服了對jtag和Tcl的恐懼心理。

    上述代碼的組織結(jié)構(gòu)如下:

1. 真實jtag操作。

1.1 檢測電纜。(如果你用的是并口下載線,并且沒有修改原代碼的話,在這一步你就會遇到攔路虎)

1.2 查找器件。(如果你的電路板上串接了不只一個jtag器件的話,你要修改你的代碼,否則這一步也是過不去的)

1.3 打開器件。(前兩關(guān)過去了,這一步應(yīng)該不成問題)

1.4 獲得器件的jtag編號。(IDCODE命令)(個人覺得沒有什么大用處,也許可以起到初始化IR的作用)



2. 虛擬jtag操作。

2.1 循環(huán)采樣計數(shù)器值。(SAMPLE命令)(通過jtag鏈路從FPGA讀數(shù)據(jù))

2.2 設(shè)置計數(shù)器初值。(FEED命令)(通過jtag鏈路向FPGA發(fā)數(shù)據(jù))

    需要說明的是,2中的SAMPLE命令(2'b01)和FEED命令(2'b10)是用戶自定義的virtual jtag命令(隨便定,只要你的verilog代碼中是對應(yīng)譯碼的就可以),1中的IDCODE命令(在Cyclone器件中是10'b0000000110)是由Altera定義的,返回值是一組32位的二進(jìn)制數(shù)。

    把上面的代碼結(jié)合著::quartus::jtag Tcl命令包的幫助文件(我已經(jīng)給了)逐條分析一下,對于::quartus::jtag Tcl命令包的使用就沒有問題了。

    我做的一個Tcl模板 Tcl模板.rar (1.03 KB, 下載次數(shù): 12) ,根據(jù)上面代碼改的,可以檢查jtag鏈路,并由用戶選擇使用哪個器件,可以讀取一次jtag數(shù)據(jù),然后由用戶輸入一次jtag數(shù)據(jù)。如果需要循環(huán)功能,還要根據(jù)上面代碼加入Tcl命令。以后有更好的再傳上來。

四、 verilog代碼分析

    先把關(guān)鍵的verilog代碼寫在下面。完整的代碼在最后,按照我的理解和習(xí)慣,對原示例代碼的寫法作了修改。
wire [3:0] counter1;
reg   [3:0] feed_reg;     // 四位的DR寄存器,用于加載輸入值

wire tdi, tck, cdr, cir, e1dr, e2dr, pdr, sdr, udr, uir;
reg   tdo, bypass_reg;
wire [1:0] ir_in;             // 兩位的IR寄存器輸出,來自my_vji_a
wire sample = ir_in[0];  // IR譯碼,2'b01表示SAMPLE命令
wire feed   = ir_in[1];    // IR譯碼,2'b10表示FEED命令

reg [3:0] offload_reg;    // 四位的DR寄存器,用于輸出


/* instantiation of the vji mega functionc */
my_vji_a VJI_INST(
.ir_out (2'b0), // input to megafunction
.tdo (tdo),      // input to mega function

.ir_in (ir_in),   // output from mega function
.tck (tck),      // output from mega function
.tdi (tdi),        // output from mgafunction

.virtual_state_cdr (cdr), // output from mega function
.virtual_state_e1dr(e1dr), // "
.virtual_state_e2dr(e2dr), //  "
.virtual_state_pdr (pdr), //  "
.virtual_state_sdr (sdr), // "
.virtual_state_udr (udr), //  "

.virtual_state_uir (uir), //  "
.virtual_state_cir (cir)); // "

/* 1. Sample Instruction Handler */  
always @ (posedge tck)  // 針對SAMPLE指令的處理
  if ( sample && cdr )
    offload_reg <= counter1;
  else if ( sample && sdr )
    offload_reg <= {tdi, offload_reg[3:1]}; // 典型的移位寄存器操作(MSB to LSB),移位輸出counter1的當(dāng)前值

/* 2. Feed Instruction Handler */
always @ (posedge tck)  // 針對FEED指令的處理
  if ( feed && sdr )
    feed_reg <= {tdi, feed_reg[3:1]}; // 典型的移位寄存器操作(MSB to LSB),移位輸入要賦給counter1的初始值
  
/* 3. Bypass register */  // 旁路寄存器,沒有針對這個virtual_jtag的操作就旁路
always @ (posedge tck)
  bypass_reg = tdi;

/* 4. Node TDO Output */  // TDO輸出選擇器,根據(jù)IR的不同,選擇不同的信號輸出
always @ ( sample, feed, feed_reg[0], offload_reg[0], bypass_reg )
begin
  if (sample)
    tdo <= offload_reg[0];
  else if (feed)
    tdo <= feed_reg[0];   // Used to maintain the continuity of the scan chain. // 在移位輸入時,也要保證jtag鏈路有輸出
  else
    tdo <= bypass_reg;
end

    上面代碼中,/* Sample Instruction Handler */之后的代碼是需要用戶自己編寫的代碼,是使用virtual_jtag的精髓所在,一定要讀懂。

    sld_virtual_jtag 的說明中把TAP控制器的狀態(tài)信號分為High level和Low level。示例代碼中使用的是High level部分的信號。High level部分的信號又可以分為DR寄存器操作對應(yīng)的一組狀態(tài)信號(6個)和IR寄存器操作對應(yīng)的一組狀態(tài)信號(2個)。

    1. DR寄存器操作對應(yīng)的一組狀態(tài)是:Capture_DR -> Shift_DR -> Exit1_DR -> Pause_DR -> Exit2_DR -> Update_DR。每一個狀態(tài)對應(yīng)一個*dr信號。

    對于數(shù)據(jù)輸出操作(此例中是SAMPLE命令,并行加載,串行輸出),需要在Capture_DR狀態(tài)把被采樣的信號并行加載到DR寄存器中,在Shift_DR狀態(tài)把DR寄存器串行輸出到virtual jtag鏈路的tdo引腳上(同時串行載入tdi引腳的數(shù)據(jù)),然后遍歷余下的狀態(tài)并不做任何操作。這一過程就是代碼中對offload_reg寄存器的操作。

    對于數(shù)據(jù)輸出操作(此例中是FEED命令,串行輸入,并行加載),在Capture_DR狀態(tài)不進(jìn)行任何操作直接跳轉(zhuǎn)到下一個狀態(tài),在Shift_DR狀態(tài)串行載入virtual jtag輸入的數(shù)據(jù),在Exit1_DR狀態(tài)把獲得的數(shù)據(jù)并行加載到目標(biāo)寄存器上,然后遍歷余下的狀態(tài)并不做任何操作。這一過程就是代碼中對feed_reg寄存器的操作。

    2. IR寄存器操作對應(yīng)的一組狀態(tài)是:Capture_IR -> Shift_IR -> Exit1_IR -> Pause_IR -> Exit2_IR -> Update_IR。由于virtual jtag模塊提供了并行的ir_in端口,簡化了操作,所以只有首尾兩個狀態(tài)對應(yīng)*ir信號。

    在這個例子中,只用到了ir_in端口,沒有用到IR操作對應(yīng)的狀態(tài)及輸出信號。這也可以看作是virtual jtag的方便之處。

    3. bypass_reg寄存器提供了jtag鏈路的第三條通路,在沒有針對當(dāng)前virtual jtag操作的情況下,tdi數(shù)據(jù)經(jīng)過一個tck周期的延時輸出到tdo引腳。

    4. tdo引腳輸出時,需要根據(jù)ir_in的取值選擇三條通路中的一條,所以這部分代碼也是需要用戶設(shè)計的。

    看懂了這個例子,對virtual jtag的基本輸出和輸入功能就掌握了。

    下圖是用lpm宏單元替換各個功能塊后編譯得到的RTL視圖。相應(yīng)的代碼可以在此 相應(yīng)的代碼.rar (4.92 KB, 下載次數(shù): 21) 下載。




作者: 赤羽    時間: 2019-9-27 23:01
好難,,之前已經(jīng)弄了一周了還是沒有搞明白。我現(xiàn)在都快要崩了啊!!!!
作者: 小泉    時間: 2019-10-13 16:04
乖乖的好難哦。不知道學(xué)進(jìn)不
作者: Samuelscc    時間: 2019-12-13 10:10
很有收獲謝謝lz




歡迎光臨 (http://m.zg4o1577.cn/bbs/) Powered by Discuz! X3.1
主站蜘蛛池模板: 91麻豆精品视频 | 日本伊人网 | 国产精品一区在线观看 | 中文在线免费观看 | 五月婷婷六月激情 | 黄色大片av | cao在线 | 在线观看视频一区二区三区 | 欧美日韩免费一区二区三区 | 91国内在线| 毛片网站视频 | 精品国产一区二区在线观看 | 日韩免费一区二区 | 91调教视频 | 狠狠干2021 | 亚洲欧美精品一区二区 | 黄色小视频免费观看 | 做爰xxxⅹ性生交 | 成人一区二区三区四区 | 久久免费高清视频 | 免费看a| 在线观看免费av网站 | 做爰xxxⅹ性生交 | 人人爽av| 涩涩视频免费看 | 中文字幕不卡视频 | 成人免费毛片入口 | 中文字幕精品在线观看 | 婷婷99 | 日韩三级精品 | 欧美在线一区二区三区 | 黄色免费观看视频 | 色综合五月天 | 视频一区在线播放 | 亚洲香蕉视频 | 国产日韩欧美视频 | 精品福利在线观看 | 国产精品日韩在线 | 一区二区国产精品 | av黄色在线观看 | 性爱视频日本 |