tag 标签: altera,virtual

相关博文
  • 热度 24
    2012-12-3 12:17
    4114 次阅读|
    9 个评论
    Virtual JTAG megafunction 端口定义 表1 VJ核输入端口 Port Name Required Description Comments tdo Yes Writes to the TDO pin on the device.   ir_out   No Virtual JTAG instruction register data. The value is available and latched when virtual_state_uir is high. Specify the width of this bus with the SLD_IR_WIDTH parameter.            表3 High-level Virtual JTAG State Signals Port Name Required Description Comments virtual_state_cdr No Indicates that virtual JTAG is in Capture_DR state.   virtual_state_sdr Yes Indicates that virtual JTAG is in Shift_DR state. In this state, this instance is required to establish the JTAG chain for this device. virtual_state_e1dr No Indicates that virtual JTAG is in Exit1_DR state.   virtual_state pdr No Indicates that virtual JTAG is in Pause_DR state. The Quartus II software does not cycle through this state using the TCL command. virtual_state_e2dr No Indicates that virtual JTAG is in Exit2_DR state. The Quartus II software does not cycle through this state using the TCL command. virtual_state_udr No Indicates that virtual JTAG is in Update_DR state.   virtual_state_cir No Indicates that virtual JTAG is in Capture_IR state.   virtual_state_uir No Indicates that virtual JTAG is in Update_IR state.     上面三个表是VJ核的基本端口描述,在VJ核的user guide或者Quartus II软件的帮助里可以找得到。               关于Virtual JTAG测试平台的建设,主要分两个部分,一个部分是基于FPGA的底层设计,主要就是例化VJ核,以及相关的逻辑接口设计;另外一个部分是应用层的用户接口(GUI)的设计,主要是采用TCL语言设计友好的用户界面。   基于Virtual JTAG的底层FPGA逻辑设计               FPGA的底层逻辑设计,在前面的“如何有效利用Virtual JTAG进行电路调试”一文中有过简略介绍。在那个文章里介绍了如何在FPGA里例化一个FIFO和VJ和进行交互,再通过TCL建立的用户接口经由VJ访问FIFO.          在实际的实践中可以将一些非实时的数据暂存在FIFO里,当需要分析的时候再从FIFO里读出来进行分析。这里我们希望介绍一些相对比较复杂的应用,在本人实际应用中,我在之前基于FIFO的基础上再加入了对FPGA内部寄存器的读写(或者说对一些参数可以进行实时地配置),另外加入了VJ对于FPGA外挂的SDRAM的访问。           前面文章已经介绍了如何例化VJ,这里不赘述,只是需要提醒的是对user来说,逻辑里只有ir_in和tck这两个端口会经常用到,另外作为状态的控制,cdr,cir,sdr,udr,以及uir这几个状态指示引脚在相关的数据或者命令锁存的时候要用到。这里给出一个简单的例子:   ------------------------------------------------------ --Tcl只负责发送写命令,写fifo的数据由FPGA自己产生 ------------------------------------------------------- process(clkin,reset) begin         if reset = '0' then              write_en = '0';         elsif clkin'event and clkin= '1' then              if ir_in = fifowr_cmd and uir = '1' then                   write_en = '1';              else                   write_en = '0';              end if;         end if; end process;   ir_in端口当前只是处于FIFO写命令状态(需要注意的是VJ根据ir_in端口宽度可以编码出一定量的命令,比如ir_in为4bit的时候最多支持16个命令,所以在搭建调试平台的时候一定要事先确定好最终你需要的命令数,当然你也可以在不够的时候进行例化修改),那么uir指示了何时可以稳定锁存此命令,这时候就相当于FPGA收到了平台发过来的写FIFO的命令了,那么到底写什么数据呢?这个可以事先约定,或者也可以通过TCL平台传递需要写入的数据,这里是根据此命令,将相关逻辑已经处理好的数据写入FIFO以待后续分析。其他状态以及命令类似处理。对于VJ逻辑模块的设计,主要是VJ核的例化,还有就是VJ各个命令的编码,接着就是对于各个编码好的命令进行相应的解码以及后续处理。比如上述代码中“ir_in = fifowr_cmd”的fifowr_cmd是个常量,是VJ命令的一个编码值,上面给出的代码就是对此命令的部分逻辑处理。         处理VJ逻辑,另外一个部分就是用户逻辑处理,比如上述FIFO的例化以及FIFO的读写控制。这里需要加入的是FPGA内部寄存器的读写控制,以及SDRAM的控制器逻辑代码。当然增加了用户逻辑,相应地也要在VJ逻辑处理里增加相应的命令编码以及解码处理逻辑。        这里增加了VJ与SDRAM的通信,只是为了调试SDRAM控制器,调试结束后,为了节约资源完全可以注释掉VJ相关部分或者全部模块。至于如何在FPGA设计SDRAM的控制器有很多人有过相关的文章,而且Xilinx和ALTERA都有参考设计可以参考,本人也有专门的博文介绍自己的体验,这里也不再赘述。本文最后的问题描述部分给出我在实际项目中使用SDRAM的时候碰到的问题以及解决过程。     基于Virtual JTAG应用层TCL用户界面设计                FPGA底层逻辑设计好以后,就是搭建应用层的用户界面,其实这两个部分可以同时交互进行,因为随着设计的丰富,你也许要逐步的增加调试项目,也即是要增加VJ的命令端口数目。在前面的两篇“Virtual JATG初探”中对于VJ TCL命令进行了相关的介绍,这里不再赘述。这里给出上述FIFO写的时候对应的VJ TCL代码   ;###FIFO Write command.通过tcl发命令给FPGA,让FPGA将FIFO写满。 proc FIFO_Push_CMD {} {      .top.t insert end "\n Command: Single Write FIFO\n"      device_lock -timeout 10000          device_virtual_ir_shift -instance_index 0 -ir_value 1 -no_captured_ir_value          set usedw          device_unlock          set tmp 0x          append tmp $usedw          set usedw               set DataWidth 32      set value            if {$usedw!=255} {          if {$value 2097152} {               .top.t insert end "\nvalue entered exceeds 21 bits\n" }                    set push_value          set diff %21}];#这里的“%”似乎没什么作用(求余数),如果去掉“%21”运行结果无变化,反正就是获取字符长度                    if {$diff != 21} {                set push_value          }                    .top.t insert end "$push_value\n"                    device_lock -timeout 10000          device_virtual_ir_shift -instance_index 0 -ir_value 4 -no_captured_ir_value                    device_virtual_dr_shift -instance_index 0 -dr_value $push_value -length 21 -no_captured_dr_value          device_unlock      } else {          .top.t insert end "\nCan't write the FIFO, for it is full now!\n"      } }   上述代码中“device_virtual_ir_shift -instance_index 0 -ir_value 4 -no_captured_ir_value”定义了ir_value为4,那么也就是在FPGA中逻辑设计中对于此命令的编码值就是4,也即常量fifowr_cmd等于4.这点一定要注意,TCL和FPGA逻辑对于命令的编码值一定要一一对应,否则就无法正确的进行命令解析以致无法正常的进行调试。   实例演示             1. 基于FIFO的测试平台                 图1 基于FIFO的测试平台        此阶段性测试平台具备以下功能:         1)、具备给FPGA发生一个系统复位功能;         2)、读取FIFO的usedw、full以及empty标志信息;         3)、给FPGA发一个命令,让其将FIFO填满数据;         4)、通过tcl将FIFO里的数据一次读出来;读出来的数据可以显示在当前text框里,同时可以存储在一个文件里供离线分析;         5)、从一个文件里往FPGA的存储器或者外挂的存储器里写入大量的初始数据;         6)、读取系统内部状态标志,一次可以读取32个标志“位”;         7)、向系统写入参数,写入的参数可以通过输入窗口进行设定。       2 . 加入SDRAM访问的测试平台 图2 加入SDRAM访问的测试平台       此阶段性测试平台具备以下功能:       1). 加入SDRAM单个写控制按钮,写入的地址和数据通过参数设置窗口设定;目前支持设置的地址和写入的数据是一样的。       2). 加入SDRAM大批量写按钮;写入的数据是通过逐一读取当前目录下的文件里的数据写入,写入的地址根据逐次写入操作加1,起始地址默认是0.       3). 加入SDRAM读按钮,此按钮可以支持单个读,以及批量读1024个地址数据;当滑动条设置为0时为批量读,非0时为单个读;批量读默认从0开始读1024个数据,单个读的地址由参数设置窗口设定。             问题描述              1. VJ测试平台访问SDRAM的问题       上述SDRAM在批次写的时候,第一个数据不是文件里的第一个数据,而是上一次留在SDRAM数据线上的数据;文件里的第一个数据被写入在第二个位置,如图2中的0地址上的数据3不是文件里的第一个数据;而文件里的第一个数据“0000”被写在了地址1位置。经过查时序,这个问题算是找到了,把第一个数据改成x“5555”,为了好看。用signaltap抓了一下发现是在大批次写的时候第一个地址是从1开始而不是0开始,而大批次读的第一个地址是0. 如图3所示 : 图3 用SignalTap找到SDRAM写问题所在 大家看最后一行的“sdr_wr_adr"正好是地址1,而此时的写入数据”data_from_sys“是我定义的第一个数据0x5555,也就是在SDRAM写的时候第一个数据0x5555没有被写入地址0.修改SDRAM的控制器解决此问题,SDRAM的读写均无问题,如图4所示。 图4 解决SDRAM访问问提       2. SDRAM single operation mode下节约访问时间的探讨       SDRAM的Single Write写如图5图所示,从c_state的状态可以看出一次完整的Single Write花费了11个时钟周期,根据SDRAM的时序关系,可以缩短状态C和E(状态E可以省略),至于为何可以缩短可以查相关的SDRAM芯片的数据手册可以得到各个命令的具体时间参数。 图5 SDRAM single Write写控制时序 修改SDRAM控制器,这里暂时保留状态E,这时候single Write控制时序如图6所示: 图6 修改后建设单个写时间的控制时序 同样对于single read模式下,如图7所示,观察状态c_state,发现整个single read需要11个时钟周期,对照SDRAM时序图,可以修改逻辑使单个读减少到6个时钟,即去除图7中的状态A . 图7 SDRAM single read模式下修改前时序关系 图8是修改后的SDRAM单个读时序图,此时没有状态A了 : 图8 修改控制器后SDRAM单个读时序图