棋子 · 3 天前

VCD文件秒变专业时序图:wavedraw让仿真波形更美观

编 者 按 

   对于那些喜欢先写代码再写文档的小伙吧,寄希望于直接把仿真的波形直接贴到文档上作为接口时序图,又嫌弃波形文件太丑的小伙伴,那么可以尝试下wavedraw的VCDParser,直接将VCD文件转换为可用于wavedrom生成波形的json文件,支持只选择某个时间窗范围内的波形提取。

VCDParser

    《告别繁琐JSON,wavedraw用Python重新定义时序图绘制》一文中已介绍了wavedraw的用法,正常研发流程里,一般都是先撰写文档过完评审然后开始写代码,最后进行仿真,也许有的小伙伴是先进行的demo验证,有一些仿真波形,那么在写文档时将方针波形贴到文档中作为接口时序,然而波形文件一般都张的较丑(文档也显得极不专业)。对于各种波形文件,一般都能转换成标准的VCD文件,VCD文件也相对简单,故在wavedraw中添加一个对VCD文件的解析并通过wavedraw提供的能力自动转换生成复符合wavedrom要求的json文件。

VCD文件通过wavedraw转换输出json格式的文件用法很简单,下图即是一个demo:

image.png

VCDParser其初始化函数定义如下:

image.png

  • fileName:用于指定VCD波形文件的位置
  • halfClockPeriod:用于指定波形中半个时钟周期的大小。对于时钟信号,在VCD波形中会记录上升沿和下降沿,同时会真实记录对应的时间轴,为避免在转换后的波形被迫拉长,这里需指定时钟周期的一半值(对于时钟周期为奇数,可能存在一点点问题)用于缩放波形。如果在波形中没有时钟,那么该值填1即可。

    通过执行VCDParser的generateWave函数可以直接生成符合wavedrom标准的json字符串输出。generateWave的函数定义如下:

image.png

  • title:指定波形的名称
  • startTime:可以用于指定截取VCD波形中开始的时间位置
  • endTime:可以用于指定截取VCD波形中的结束时间位置,其与startTime配合使用用于截取指定时间窗口的波形,如果任意一个值为None,那么则会将整个波形的都进行转换。
  • period:用于指定生成波形中的period参数,如果波形中带有时钟,则建议该值设置为0.5,否则设置为1

    上面这段代码读取的VCD是不带时钟的,直接执行即可得到输出的json格式波形描述:

{"signal":[
{"name":"lru_state","wave":'2..3..4..5..6..7..8..9..2..3..4..5.',"data":["0x0","0xe","0xdc","0xb98","0x7310","0x3b10","0x7310","0x620e","0x40dc","0xb98","0xa8e","0x7206"],"node":'..................................',"period":1,"phase":0},
{"name":"lru_entry","wave":'2..3..4..5..6........7..8..9.....2.',"data":["0x0","0x1","0x2","0x3","0x0","0x1","0x2","0x3","0x1"],"node":'..................................',"period":1,"phase":0},
{"name":"lru_update_req_lru_state","wave":'2.3..4..5..6..7..8..9..2..3..4..5..',"data":["0x14c3","0x0","0xe","0xdc","0xb98","0x7310","0x3b10","0x7310","0x620e","0x40dc","0xb98","0xa8e"],"node":'..................................',"period":1,"phase":0},
{"name":"lru_update_req_lru_update_entry","wave":'2.3..4..5..6..7..8..9..2..3..4..5..',"data":["0x2","0x0","0x1","0x2","0x3","0x2","0x3","0x0","0x1","0x2","0x0","0x3"],"node":'..................................',"period":1,"phase":0},
{"name":"lru_update_result","wave":'2.3..4..5..6..7..8..9..2..3..4..5..',"data":["0x1b83","0xe","0xdc","0xb98","0x7310","0x3b10","0x7310","0x620e","0x40dc","0xb98","0xa8e","0x7206"],"node":'..................................',"period":1,"phase":0},
{"name":"clk","wave":'0..................................',"node":'...................................',"period":1,"phase":0},
{"name":"reset","wave":'1..................................',"node":'...................................',"period":1,"phase":0},
["LruControl",
{"name":"lru_state","wave":'2..3..4..5..6..7..8..9..2..3..4..5.',"data":["0x0","0xe","0xdc","0xb98","0x7310","0x3b10","0x7310","0x620e","0x40dc","0xb98","0xa8e","0x7206"],"node":'..................................',"period":1,"phase":0},
{"name":"lru_entry","wave":'2..3..4..5..6........7..8..9.....2.',"data":["0x0","0x1","0x2","0x3","0x0","0x1","0x2","0x3","0x1"],"node":'..................................',"period":1,"phase":0},
{"name":"lru_update_req_lru_state","wave":'2.3..4..5..6..7..8..9..2..3..4..5..',"data":["0x14c3","0x0","0xe","0xdc","0xb98","0x7310","0x3b10","0x7310","0x620e","0x40dc","0xb98","0xa8e"],"node":'..................................',"period":1,"phase":0},
{"name":"lru_update_req_lru_update_entry","wave":'2.3..4..5..6..7..8..9..2..3..4..5..',"data":["0x2","0x0","0x1","0x2","0x3","0x2","0x3","0x0","0x1","0x2","0x0","0x3"],"node":'..................................',"period":1,"phase":0},
{"name":"lru_update_result","wave":'2.3..4..5..6..7..8..9..2..3..4..5..',"data":["0x1b83","0xe","0xdc","0xb98","0x7310","0x3b10","0x7310","0x620e","0x40dc","0xb98","0xa8e","0x7206"],"node":'..................................',"period":1,"phase":0},
{"name":"clk","wave":'0..................................',"node":'...................................',"period":1,"phase":0},
{"name":"reset","wave":'1..................................',"node":'...................................',"period":1,"phase":0},
{"name":"lru_row_state","wave":'2..3..4..5..6........7..8..9.....2.',"data":["0xf","0xe","0xc","0x8","0x1","0x2","0x4","0x8","0x2"],"node":'..................................',"period":1,"phase":0},
{"name":"lru_row_state_ohFirst_input","wave":'2..3..4..5..6........7..8..9.....2.',"data":["0xf","0xe","0xc","0x8","0x1","0x2","0x4","0x8","0x2"],"node":'..................................',"period":1,"phase":0},
{"name":"lru_row_state_ohFirst_masked","wave":'2..3..4..5..6........7..8..9.....2.',"data":["0x1","0x2","0x4","0x8","0x1","0x2","0x4","0x8","0x2"],"node":'..................................',"period":1,"phase":0},
{"name":"lru_row_state_oh","wave":'2..3..4..5..6........7..8..9.....2.',"data":["0x1","0x2","0x4","0x8","0x1","0x2","0x4","0x8","0x2"],"node":'..................................',"period":1,"phase":0},
{"name":"lru_update_entry_oh","wave":'2.3..4..5..6..7..8..9..2..3..4..5..',"data":["0x4","0x1","0x2","0x4","0x8","0x4","0x8","0x1","0x2","0x4","0x1","0x8"],"node":'..................................',"period":1,"phase":0},
],
],
"head":{"text":"wave","tick":0},
"config":{"hscale":1}}

    直接生成时序图:

image.png

写在最后

    在github上已上传该功能,并附带的又对应的demo(vcdTest.py),感兴趣的小伙伴可以自行去安装尝试,“阅读原文”中附带github地址。

    这里的测试都是基于SpinalHDL仿真生成的VCD文件进行测试,后续其他功能如只挑选指定信号波形生成、截取多个时间窗口生成等功能再进行完善。

END

作者:玉骐
文章来源:Spinal FPGA

推荐阅读

更多 IC 设计干货请关注IC设计专栏。欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。

推荐阅读
关注数
20362
内容数
1310
主要交流IC以及SoC设计流程相关的技术和知识
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息