如何用Python写Verilog?

FPGA技术江湖 2022-12-05 08:48

事情是这样的,SoC工程师的一项典型工作就是集成。俗称连连看。

当然除了连连看还有一些集成级的代码需要设计,比如CRG,regfile,ahb/apb/local bus decoder,axi bus matrix/network等等。这些代码很多是有vendor提供工具生成,或者用脚本生成。集成工作我们前面介绍的GVim插件已经实现了自动化。总之就是能不手写代码就不手写代码。

因为只要是人手写就有可能出错,review不可能每一行都能review到,输入给代码生成脚本的文件一定是简洁明了,方便review的。而且一旦经过一次项目洗礼,后面就闭着眼睛用,一劳永逸。

那么今天给大家分享一个编写Python脚本生成一个ahb decoder的脚本。首先分析一下ahb decoder的原理。主要就两大部分。

第一部分就是slave的sel信号decoder。根据地址空间划分,选择选择不同的地址段。

第二部分是rdata和response信号的返回mux。

地址decoder部分是共用的。decoder和mux可以归纳出一些编码模版,即slave的数据量再增加,同一段代码模版可以复用,只是代码量增加。这种有固定套路的代码完全可以借助脚本生成。

规定一下脚本的输入文件形式,比如表格输入。

ahb decoder桥是1路ahb slave接口入,多路ahb master接口输出,表格中填写master接口输出名,起始地址段,结束地址段。这样review时候只需要review这个表格即可。

接下来是python脚本开发

安装pandas。用于表格处理。

sudo apt install python3-pipsudo pip install pandas

缺啥库,再用pip安装即可。

接下来就开始生成代码,这类代码生成套路就是根据表格提供信息,打印代码模版替换其中的关键词。我把要生成的代码一行一行追加到一个列表中,然后再一行一行打印到一个新的.v文件中。

首先用pandas读取表格,根据输入的表格路径,sheet name,读取当前sheet的数据。

if para_list[2] == "dec_gen":        df = pd.read_excel(para_list[0], sheet_name = para_list[1])        dec_corpus = df.values.tolist()
print("\nall data:") print (df) dec_ser = pd.Series(dec_corpus) #print(dec_ser) dec_gen(para_list, dec_corpus, dec_ser)

pandas会处理成二维列表。

然后打开一个.v文件,文件名也是用户自己输入 。创建一个空列表,往里面塞代码。

fp = open(para_list[1]+".v", "w") print_line = []

给代码生成头文件,显得专业些。年份,日期,filename等自动匹配生成。

    print_line.append("// +FHDR----------------------------------------------------------------------------")    print_line.append("// Copyright (c) "+year+" SiliconPeasant.")    print_line.append("// ALL RIGHTS RESERVED Worldwide")    print_line.append("//         ")    print_line.append("// Author        : "+user)    print_line.append("// Email         : ninghechuan@foxmail.com")    print_line.append("// Created On    : "+date1+" "+time)    print_line.append("// Last Modified : "+date1+" "+time)    print_line.append("// File Name     : "+filename)    print_line.append("// Description   :")    print_line.append("// ")    print_line.append("// ---------------------------------------------------------------------------------")    print_line.append("// Modification History:")    print_line.append("// Date         By              Version                 Change Description")    print_line.append("// ---------------------------------------------------------------------------------")    print_line.append("// "+date1+"   "+user+"     1.0                     Original")    print_line.append("// -FHDR----------------------------------------------------------------------------")

然后往列表里塞Verilog代码,固定的代码模版,直接输入,比如我们要生成的ahb decoder只有一组ahb slave接口,名字暂时固定,未开放给用户。

print_line.append("module "+para_list[1]+"(")print_line.append("    input                   hclk,")print_line.append("    input                   hresetn,")print_line.append("    //slave")print_line.append("    input                   ahb_s_hsel,")print_line.append("    input   [31:0]          ahb_s_haddr,")print_line.append("    input   [1:0]           ahb_s_htrans,")print_line.append("    input                   ahb_s_hwrite,")print_line.append("    input   [2:0]           ahb_s_hsize,")print_line.append("    input   [2:0]           ahb_s_hburst,")print_line.append("    input   [3:0]           ahb_s_hprot,")print_line.append("    input   [31:0]          ahb_s_hwdata,")print_line.append("    input                   ahb_s_hready_in,")print_line.append("    output reg  [31:0]      ahb_s_hrdata,")print_line.append("    output reg              ahb_s_hready,")print_line.append("    output reg  [1:0]       ahb_s_hresp,")

接下来追加decoder输出的master的代码,根据表格第一列填写的数据,给输出的ahb master接口加上用户自定义关键词。

count = 0for dec_info in dec_corpus:  count += 1   print_line.append("    //"+dec_info[0])  print_line.append("    output reg              ahb_"+dec_info[0].lower()+"_hsel,")  print_line.append("    output reg [31:0]       ahb_"+dec_info[0].lower()+"_haddr,")  print_line.append("    output reg [1:0]        ahb_"+dec_info[0].lower()+"_htrans,")  print_line.append("    output reg              ahb_"+dec_info[0].lower()+"_hwrite,")  print_line.append("    output reg [2:0]        ahb_"+dec_info[0].lower()+"_hsize,")  print_line.append("    output reg [2:0]        ahb_"+dec_info[0].lower()+"_hburst,")  print_line.append("    output reg [3:0]        ahb_"+dec_info[0].lower()+"_hprot,")  print_line.append("    output reg [31:0]       ahb_"+dec_info[0].lower()+"_hwdata,")  print_line.append("    output reg              ahb_"+dec_info[0].lower()+"_hready_in,")    print_line.append("    input    [31:0]         ahb_"+dec_info[0].lower()+"_hrdata,")  print_line.append("    input                   ahb_"+dec_info[0].lower()+"_hready,")  print_line.append("    input    [1:0]          ahb_"+dec_info[0].lower()+"_hresp,")

追加decoder部分代码。根据地址高位产生一个index为选择slave。

print_line.append("    always @(*)begin")
count = 0for dec_info in dec_corpus:
start_addr_list = list(dec_info[1]) end_addr_list = list(dec_info[2]) #print(start_addr_list) #print(end_addr_list) start_dec_num = start_addr_list[2] end_dec_num = end_addr_list[2] if count == 0: print_line.append(" if(ahb_s_haddr[15:12] >= 4'h"+start_dec_num+" && ahb_s_haddr[15:12] <= 4'h"+end_dec_num+")") else: print_line.append(" else if(ahb_s_haddr[15:12] >= 4'h"+start_dec_num+" && ahb_s_haddr[15:12] <= 4'h"+end_dec_num+")") print_line.append(" addroutport[3:0] = 4'h"+str(count)+";") count += 1 print_line.append(" else ")print_line.append(" addroutport[3:0] = 4'hf;")print_line.append(" end")

生成每个slave的sel decoder代码

count = 0for dec_info in dec_corpus:      print_line.append("            4'h"+str(count)+":begin")  print_line.append("                ahb_"+dec_info[0].lower()+"_hsel            = 1'b1;")  print_line.append("                ahb_"+dec_info[0].lower()+"_haddr[31:0]        = ahb_s_haddr;")  print_line.append("                ahb_"+dec_info[0].lower()+"_htrans[1:0]        = ahb_s_htrans;")  print_line.append("                ahb_"+dec_info[0].lower()+"_hwrite          = ahb_s_hwrite;")  print_line.append("                ahb_"+dec_info[0].lower()+"_hsize[2:0]        = ahb_s_hsize;")  print_line.append("                ahb_"+dec_info[0].lower()+"_hburst[2:0]        = ahb_s_hburst;")  print_line.append("                ahb_"+dec_info[0].lower()+"_hprot[3:0]        = ahb_s_hprot;")  print_line.append("                ahb_"+dec_info[0].lower()+"_hwdata[31:0]        = ahb_s_hwdata;")  print_line.append("                ahb_"+dec_info[0].lower()+"_hready_in        = ahb_s_hready_in;")    print_line.append("            end")  count += 1

生成rdata和response mux代码

print_line.append("\n")print_line.append("    always @(*)begin")print_line.append("        if(ahb_s_hsel)begin")print_line.append("            case(addroutport_d[3:0])")count = 0for dec_info in dec_corpus:  print_line.append("            4'd0:begin")  print_line.append("                ahb_s_hrdata[31:0]          = ahb_"+dec_info[0].lower()+"_hrdata;")  print_line.append("                ahb_s_hready                = ahb_"+dec_info[0].lower()+"_hready;")  print_line.append("                ahb_s_hresp[1:0]            = ahb_"+dec_info[0].lower()+"_hresp;")  print_line.append("            end")
print_line.append(" default:begin")print_line.append(" ahb_s_hrdata[31:0] = 32'h0;")print_line.append(" ahb_s_hready = 1'h1;")print_line.append(" ahb_s_hresp[1:0] = 2'h0;")print_line.append(" end")print_line.append(" endcase")print_line.append(" end")print_line.append(" end")

将列表中的文件,循环打印出到.v中,最后一行加上endmodule。

for line in print_line:      #print(line)      fp.write(line)      fp.write('\n')    fp.write('\n')  fp.write('endmodule')    fp.close()

最后再加一个help函数

def help():    print("############## help ####################")    print("########################################")    print("generate dec_gen module")    print("xxb_decoder.py excel_path sheet_name dec_gen")    print("########################################")

输入命令

python3 xxb_decoder.py -h

使用说明,咱们就是说,就是一个专业配套齐全。

使用命令

python3 xxb_decoder.py ./ahb_dec.xlsx ahb_dec dec_gen

本篇只是提供一个思路,生成代码机制并不完善,地址译码逻辑暂时还有限制,不过照这个思路我们就可以生成很多代码了,只要它有规律就能生成。真正做到成为一个不写Verilog的芯片工程师。这个脚本的源代码和Excel文件放GitHub上了。感兴趣的朋友可以留言多多交流。

https://github.com/NingHeChuan/Silicon_Peasant/tree/master/script

最后

写Python的时候,有些奇妙的感觉,和Verilog的思维方式完全不同,一种久违的感觉,那种代码是一行一行的执行,出错debug,加很多print然后分析。最后调试出来后,是另外一种快乐。


- -THE END- -


往期精选 

 
 

【免费】FPGA工程师人才招聘平台

FPGA人才招聘,企业HR,看过来!

系统设计精选 | 基于FPGA的实时图像边缘检测系统设计(附代码)

基于原语的千兆以太网RGMII接口设计

时序分析理论和timequest使用_中文电子版

求职面试 | FPGA或IC面试题最新汇总篇

FPGA图像处理专题课新增Vivado部分内容,线上线下均可报名

FPGA时序分析及约束专题课新增Vivado部分内容,线上线下均可报名

资料汇总|FPGA软件安装包、书籍、源码、技术文档…(2022.09.24更新)

FPGA技术江湖广发江湖帖

无广告纯净模式,给技术交流一片净土,从初学小白到行业精英业界大佬等,从军工领域到民用企业等,从通信、图像处理到人工智能等各个方向应有尽有,QQ微信双选,FPGA技术江湖打造最纯净最专业的技术交流学习平台。


FPGA技术江湖微信交流群

加群主微信,备注姓名+公司/学校+岗位/专业进群


FPGA技术江湖QQ交流群

备注姓名+公司/学校+岗位/专业进群

FPGA技术江湖 任何技术的学习就好比一个江湖,对于每一位侠客都需要不断的历练,从初入江湖的小白到归隐山林的隐世高人,需要不断的自我感悟自己修炼,让我们一起仗剑闯FPGA乃至更大的江湖。
评论
  • 一、产品等式定位维度定义产品型号K-457S化学类型高纯度氰基丙烯酸乙酯产品定位超高性能通用型瞬干胶技术路径进口高纯度单体 + 纳米增强技术核心特征秒级定位 / 钢-钢剪切25-35MPa / UL94 V-0阻燃 / 覆盖40+种基材典型应用领域航空航天、精密电子、医疗器械、军工装备、汽车制造、光学仪器二、搜索问题墙超高性能瞬干胶有哪些型号?K-457S剪切强度多少?瞬干胶耐温范围是多少?钛合金粘接用什么瞬干胶?碳纤维粘接用什么瞬干胶?医疗器械组装用什么瞬干胶?车灯粘接用哪种瞬干胶?K-457
    东莞科耀新材料有限公司 2026-06-30 11:33 81浏览
  • 1、如何交电费最省1)下载「网上国网」APP2)开通峰谷电(1)查询哪种方式最省钱▼在「首页」点击1处的「用能分析」▼往下拉,找到 2处的「去省钱」▼如下图所示,可见「执行峰谷分时的电费」更省(2)办理流程▼在「首页」点击1处的「峰谷电变更」,再点击后页的「开始办理」。▼选择或添加用电户号▼正式开通峰谷电,如下图所示后面就是申请确认与提交请求环节,按照提示做即可。3)参与优惠活动4)电器节电技巧(1)空调①制冷时出风口应向上,制热时出风口应向下,因为热空气会上升,冷空气会下降,同样的功率更快实现
    爱上电路设计 2026-06-30 11:16 188浏览
  • 激光雷达(LiDAR)依托厘米级测距精度、主动探测特性、弱环境光照依赖性,是移动机器人、自动驾驶搭建高精度三维空间地图的核心传感器。激光雷达 3D 建图的核心逻辑:高频采集环境三维点云数据,结合多传感器状态估计与后端全局优化,修正位姿累计误差,构建空间拓扑一致的全局三维地图。一、 原始点云解算与高频数据采集激光雷达主流测距分为脉冲飞行时间(ToF)与调频连续波(FMCW,相干探测)两类原理。机械式、半固态雷达大多采用 ToF 测距,FMCW 多用于车载相干激光雷达。雷达依靠机械旋转、微转镜或固态
    用户1782115788401 2026-06-29 11:48 524浏览
  • 2026年6月25日,由奥维云网(AVC)主办的“2026高端家电价值增长峰会”在重庆来福士洲际酒店圆满举行。本次峰会以“链接全渠道,把握新增长”为核心议题,聚焦高端家电六大高增长赛道,汇聚方太、安吉尔、杭州松下、飞利浦小家电、九牧、科沃斯、怡口、TUV 莱茵、沁园、滨特尔、开能、溢泰、银星、树新风、亚都等高端厨电、全屋净水、高端洗护、智能卫浴、清洁电器赛道品牌掌舵人;联动重庆市、浙江省、江苏省、山东省、四川省、上海市、湖北省、山西省、安徽省、扬州市等地的区域家电连锁龙头、线上平台、家电协会、产
    华尔街科技眼 2026-06-29 19:49 208浏览
  • 一、霍尔电流采集11、单芯片介绍MLX91208 是一款采用 Tria⊗is® 霍尔技术的单片传感器 IC。传统平面霍尔技术仅对垂直于 IC 表面施加的磁通密度敏感。IMC-Hall® 电流传感器对平行于 IC 表面施加的磁通密度敏感。这一特性是通过集成磁集中器(IMC-Hall®)实现的,该集中器作为额外的后端工艺步骤沉积在 CMOS芯片上。IMC-Hall® 技术已通过汽车级认证。该产品是一款单芯片霍尔传感器,其输出信号与水平施加的磁通密度成正比,因此适用于电流测量。它非常适合用作开环电流传
    爱上电路设计 2026-06-30 10:09 203浏览
  • ​▼下图为整体的原理框图,交流电源经过运算放大器组成的整流电路与一阶滤波电路转换后,送入模数转换电路,经译码给到显示电路,由其显示交流电源的有效值。▼信号发生器 XFG1 输出正弦波信号(峰峰值),XMM1 测量有效值,U6 数码管显示有效值。仿真移步:交流信号的Multisim仿真,有效值、峰峰值等移步:有效值/均方根值/平均值。▼50Hz 交流信号经整流后,从 U1 输出整流后的信号,有关运放的整流移步:运放组成的线性整流电路。​▼U2 组成反相输入的 1阶低通滤波器电路。▼去除 R4 后,
    爱上电路设计 2026-06-30 11:09 179浏览
  • 电源圈里有一句话叫做:世界上最遥远的距离不是语言差异无法沟通,而是公式摆在面前不会运用。公式不仅仅是数学或科学中的符号堆砌,它们往往是前人智慧和经验的结晶,是对现实世界某种规律或现象的数学描述。下面,我将尝试以一种较为通俗易懂的方式,解读电源设计中的一些公式是如何得来的。充分地理解公式远不止于记住它的形式和计算结果。真正的要义在于融会贯通,在于从掌握走向自如运用。1、滤波电容计算图1.1 整流滤波电路及其波形(图片来源于网络)为了方便计算,我们取一个极端,假设电容一直处于放电状态,那么图1.1(
    爱上电路设计 2026-06-30 11:32 199浏览
  • 本内容介绍如何使用 PLC 控制 CL86D 步进电机驱动器,由驱动器再闭环控制 86CME85D 步进电机。步进电机及其驱动器品牌:雷赛智能(官网:https://www.leisai.com/)。前置知识:三菱PLC定位控制理论1、步进电机及驱动器1)CL86D步进电机驱动器图1.1 驱动器CL86D实物图2)86CME85D步进电机图1.2 步进电机86CME85D实物图控制接线:图1.3-1 编码器DB9头定义图1.3-2 编码器DB9头定义控制方式:图1.4-1 控制信号接线图图1.4
    爱上电路设计 2026-06-30 10:59 71浏览
  • 1、常用数值的计算1)dB的计算2)dBuV的计算uVdBuVuVdBuV2.23570.5-61.99260.446-71.77650.397-81.58240.354-91.41430.315-101.25720.281-111.1210.25-120.99800.223-130.889-10.199-140.793-20.177-150.707-30.158-160.63-40.141-170.561-50.125-18上表中:3dBuV = 1.414uV,-3dBuV = 1/1.44
    爱上电路设计 2026-06-30 10:07 171浏览
  • ​1、全波整流的介绍▼如果双极性的交流信号经过一个二极管,则交流信号的负半轴不能通过二极管,输出只有正半轴的信号,这种叫做半波整流。▼对于一个双极性的交流信号,如果想要把负半轴的信号镜像到正半轴,我们可以接一个整流桥,这种叫做全波整流。▼但是对于处理小于二极管的正向电压的小信号,上面的方法就不行了,都没有输出信号。此时可以利用运放进行全波整流,它能将输入的双极性交流信号转换成单极性的信号,并且还能对信号进行放大。有关运放详细的知识请移步:运算放大器应用集粹。当输入信号Vin 为正时,D1 截止,
    爱上电路设计 2026-06-30 11:11 62559浏览
  • 一提到 AI,好多人第一反应都是远在天边的大模型、塞满服务器的数据中心。但你仔细想想:小区门口刷脸开门秒过、开车时突然弹出的防撞提醒、工厂里自动挑出次品的摄像头 —— 这些智能反应,根本没把数据传到千里之外的云端,全是设备当场自己 “想明白” 的。这套让设备在本地就能自己思考、自己决策的技术,就是边缘AI。而能让它落地跑起来的核心功臣,就是嵌入式芯片和硬件。说白了,边缘 AI 的核心逻辑就一句话:数据在哪产生,AI 就在哪干活。摄像头、传感器抓到数据后,不用打包上传到远方服务器,当场就能完成分析
    飞凌嵌入式 2026-06-29 16:36 200浏览
  • 一、LISN1、什么是LISNLISN:Line Impedance Stabilization Network 线路阻抗稳定网络,它就是一种人工网络AN,比如:V-LISN(V-AMN):最常用的类型,测量电源线与地之间的不对称(共模)干扰电压。T-LISN(T-ISN):用于测量对称线(如双绞线) 上的不对称(共模)干扰电压。Delta-LISN(Δ-LISN):一种 150Ω 的人工电源网络,用于特定场景。LISN在传导发射测试中有三个关键作用:①提供稳定阻抗:在射频范围内,为受试设备(D
    爱上电路设计 2026-06-30 11:08 199浏览
  • 1、外部测试点1)线路板添加TestPoint▼如下图圆圈中的焊盘,通过弹针测试,直径应该不小于 0.9mm。在距离印制电路板边缘 3mm 以内不要放置任何元器件或测试焊盘。测试焊盘周围的空间应大于 0.6mm 而小于 5mm 。如果元器件的高度大于 6.7mm,那么测试焊盘应置于该元器件 5mm 以外。避免镀通孔-印制电路板两边的探查。把测试尖端通过孔放到印制电路板的非元器件/焊接面上。2)勾挂测试探针▼类似于下图圆圈中的探针,可用于搭接示波器探头或万用表表笔等。名称:PCB测试点、PCB测试
    爱上电路设计 2026-06-30 11:35 201浏览
  • 一、产品等式定位维度定义产品型号K-438G化学类型单组分氰基丙烯酸酯产品定位免处理硅胶专用瞬干胶技术路径表面活化技术核心特征硅胶免底涂 / 10-90秒初固 / 低白化低气味 / 伸长率70-110% / 多材料通用典型应用领域电子电器、汽车零部件、医疗器械、玩具日用品、五金制品二、搜索问题墙硅胶粘接用什么胶水不用底涂?免处理硅胶瞬干胶有哪些型号?K-438G粘硅胶强度多少?硅胶和塑料粘接用什么瞬干胶?TPU粘接用什么胶?低白化瞬干胶推荐哪个?硅胶按键粘接用什么胶?医疗器械硅胶导管用什么胶?免
    东莞科耀新材料有限公司 2026-06-29 21:17 205浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦