HAPS系统中的UMRBus

基本概念

UMRBus是HAPS系统中用于在用户Host PC和HAPS系统(FPGA板卡)之间进行通信的一个总线协议。UMRBus定义了从硬件到软件的一整套交互协议,可以让用户方便的将上位机软件和HAPS系统进行软件上的集成。除了支持数据交互之外,UMRBus还支持硬件中断的定义,每一个UMRBus的实例都可以定义一个中断触发信号和16位位宽的中断类型信号的传输,UMRBus中断还包含了握手信号,可以保证中断被正确的响应。

在HAPS系统中,集成UMRBus也是非常简单的,一般我们可以通过例化以下三种实例来实现UMRBus模块在HAPS中的定义:

  1. capim, 用于例化整个UMRBus系统,一般HAPS系统会自动例化,用户无需手动指定
  2. capim_ui, 常用的,包含capim所有信号和总线的时钟和复位信号,时钟和复位信号可以用于用户自己的逻辑
  3. capim_wp_ui, 接口最完整,支持UMRBus总线地址和类型的动态定义。

接口定义

我们来看看这三个模块端口的一些基本定义:

名称方向capimcapim_uicapim_wp_ui描述
clkINYNNUMRBus系统的全局时钟
resetINYNNUMRBus系统的全局复位
umr_clkOUTNYYUMRBus系统时钟输出,用户可以用于自己的逻辑
umr_resetOUTNYYUMRBus系统复位输出,用户可以用于自己的逻辑
umr_capim_addressINNNY替代UMR_CAPIM_ADDRESS的动态可配置UMRBus地址
umr_capim_typeINNNY替代UMR_CAPIM_TYPE的动态可配置的UMRBus类型
doutOUTYYY32位位宽的数据输出端口
wrOUTYYY写使能,高代表DOUT上的数据有效
dinINYYY32位位宽的数据输入端口
rdOUTYYY读数据,高代表UMRBus将din的数据读走
intrINYYY中断请求,高代表在UMRBus上产生一个对Host的中断请求,
不使用的时候一定要接1'b0
intaOUTYYY中断响应,高代表pending的中断得到响应,中断响应之后intr应该清零
inttypeINYYY16位位宽的中断类型
umr_in_datOUTYNNN位的数据输出(来自HOST或者前一个UMRBus),
属于硬件接口,宽度根据不同HAPS而有区别
umr_in_enOUTYNN数据使能信号
umr_in_validOUTYNN数据有效信号
umr_out_datINYNNN位的数据输入(到HOST或者下一个UMRBus),
属于硬件接口,宽度根据不同HAPS而有区别
umr_out_enINYNN数据使能信号
umr_out_validINYNN数据有效信号

从上面的表中对我们可以看到,UMRBus实际上就是一个FIFO的接口,因为数据的发起方一直都是HOST,所以RD信号实际也是一个输出信号,这个是和一般的信号接口是有一定的却别的。

类FIFO的接口,因为没有地址信号,所以使用起来稍微有点麻烦,比我我们如果想用UMRBus去更新一个ROM的memory,这个时候就需要们自己产生一个地址累加的控制逻辑,这块还是要注意一些的。为了更好的理解这些接口,我们来看看接口上的时序图:

UMRBus_Read_Write.png

接口上我们可以看到UMRBus也有连续读写的情况,这个用于更新ROM还是非常方便的,不过UMRBus总线传输还是有一定限制的,总线不能支撑32位的数据按照100MHz时钟传输,所以即使是连续传输的情况,数据中间可能也会有短暂的停顿。

UMRBus的地址和类型

UMRBus系统实际上是一个串联的结构,类似JTAG扫描链的数据传输方式使得结构简单,易于系统扩展。和一般的系统一样,UMRBus中也有地址信息,这个地址是用来区分UMRBus各个实例,所以在例化UMRBus的时候我们要注意以下一些参数:

参数范围意义
UMR_CAPIM_ADDRESS0-63CAPIM的地址
UMR_CAPIM_TYPE0x0001 to 0xFFFFCAPIM的类型
UMR_DATA_BITWIDTH1, 2, 4, 8, 16 or 32UMR物理接口数据宽度,不同系统宽度不同
UMR_CAPIM_COMMENT_STRINGany stringHAPS 编译log中的注释信息

上述参数中比较重要的就是UMR_CAPIM_ADDRESSUMR_CAPIM_TYPE,不过一般系统中并不会用到太多的UMRBus实例,所以我个人还是习惯将UMR_CAPIM_ADDRESS=1,只是通过UMR_CAPIM_TYPE区分不同的UMRBus实例,这两个参数在HOST打开相应的UMRBus的时候都会使用到。

对于UMR_CAPIM_TYPE我们并不是所有的值都可以使用,一般要遵循以下的限制:

  • 0x0000h 是一个保留的类型,系统中禁止使用
  • 0x0001h – 0x7FFFh 是全局的类型,用于系统配置,是HAPS系统使用的用于配置系统的类型,一般用户不要使用这些类型
  • 0x8000h–0xFFFFh 没有限制的,用户可以任意使用的类型,不过我曾经试了一个0xABCD,似乎没能正确识别,所以我个人还是选择从0xA000开始的类型。

接口的例化实例

有了前面一堆的介绍,想必大家对于UMRBus已经有了一个大致的了解了,下面我们就来看看一个具体的使用实例:

capim_ui #(
    // .UMR_CAPIM_ADDRESS(1), 
    .UMR_CAPIM_TYPE(16'hA001), 
    .UMR_CAPIM_COMMENT_STRING("I_CAPIM_1")
) capim_led_control ( 
    .umr_clk (umr_clkout), 
    .umr_reset (), 
    .wr(capim_data_wr), 
    .dout(capim_data_do), 
    .rd (capim_data_rd), 
    .din(capim_data_di), 
    .intr(1'b0),
    .inta (),
    .inttype(16'h0000) 
);

上述例子中UMR_CAPIM_ADDRESS实际上也可以不指定,这样系统可以根据需要自动分配地址。比较关键一个参数就是UMR_CAPIM_TYPE,我们一般都是通过这个参数去定位我们例化的UMRBus的实例,所以这个类型的值一般不要重复。对于例化实例的输出端口,如果没有需要可以不做连接,只选取我们需要的接口信号即可。

PC端的软件接口

HAPS在PC端提供C和tcl的接口,C是可供调用的库文件,用户可以在自己的C应用中建立和UMRBus建立通信,这一般用于基于HAPS的系统开发。而对于只是基于HAPS系统进行ASIC原型验证,我们一般还是选择更为简单方便的tcl脚本接口,比如:

set rom [umrbus_open 8 1 1]
umrbus_write_list rom $rom_data
set last_addr [umrbus_read rom 1]
puts "Rom total $last_addr words downloaded, reset...."

这样就可以实现通过UMRBus对系统ROM进行更新,这和通过更新bit的方式相比,可以大大的减少更新程序的时间,更新一个HAPS系统bit一般需要十几分钟,而UMRBus下载只需几秒钟,可以大大提高开发效率。

umrbus_open的命令格式是umrbus_open [host/IP] device bus address,这些参数可以通过umrbus_scan获得。

总结

UMRBus实际上是一套非常完善的软硬件联合的解决方案,使用比较简单,上位机的配套软件也比较全,FPGA中的例化比较简单,是一个非常不错的工具,应用得当可以实现各种高级复杂的应用,比如可以实现很多IP的联合仿真,应用简单方便。

相关文章

发表新评论