阅读与解析:nvdla epython用于自动生成状态机编码的实例

英伟达深度学习加速器开源项目nvdla(NVIDIA Deep Learning Accelerator)中用到了一个python脚本epython。源代码地址:

https://github.com/nvdla/hw/blob/master/tools/bin/epython

epython全称embeded python utility,简单地说,就是用来预处理verilog文件中嵌入的python脚本。利用python语法的简洁性,来自动生成一些重复的、有规律的代码。

提出问题

我们在写Verilog代码时,状态机的编码一般是由parameter定义,如下:

如果中间需要插入一个新状态,就可能要修改两部分。一是位宽可能加1,二是新插入的后面所有的状态都需要加1。

二进制、十进制、十六进制,可以利用Vim或Emacs列编辑、数据填充、格式化来重新编码。如果是格雷码或者独热码就会麻烦很多。

那么有没有一种比较简便的方法呢?

epython的一个应用

我们知道epython可以让verilog中嵌入python脚本,那么我们可以写一个脚本来做这个事情。

假设我们有若干个状态,用python的列表来描述就是:

st = ['IDLE', 'START', 'NEW', ‘DO_SOMETHING’, 'DONE']

那么我们是否可以仅跟据这个列表来自动产生localparam的定义呢?我们的目标是下面这个样子:

我的方法步骤如下:

1. 计算列表长度,也就是状态个数stat_num

2. 计算状态编码的位宽,log2(stat_num),再向上取整

3. 把0, ..., stat_num-1进行编码转换,转成二、十、十六进制、gray、onehot等

4. 格式化输出

是不是很简单?

为了verilog中的嵌入python的简洁,我把主要的实现过程放在了python的module里,再import进来。最终手写verilog代码如下:

执行epython后,如下:

格雷码效果如下:

独热码效果如下:

是不是效果还可以?

vloglib.py代码分析

代码如下:

要点:

math是数学库,使用了log2()和ceil()两个函数来计算位宽

string的ljust(len)是指定宽度len,左对齐,不足的用空格填充。len由状态字符串的最大长度决定。

二、十、十六进制可以用sting.format()来格式化,再rjust(len)右对齐,填充‘0’

格雷码调用了一个第三方库bin2gray2bin

独热码采用字符串序列的拼接,来实现左移的效果

源码下载

下载地址:

https://github.com/chenfengrugao/vloglib

或者

git clonehttps://github.com/chenfengrugao/vloglib.git

欢迎关注ExASIC

分享数字集成电路设计中的经验和方法

分享让工作更轻松

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181213G0LJTS00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券