表格:
register name | address | field name | 属性 | bit MSB | bit LSB | 默认值 | 备注 | io |
reg1 | 0x4 | version | RO | 3 | 0 | 0 | FPGA版本 | i |
start | WC | 31 | 16 | 0 | 版本加载 | o | ||
int_status | RC | 15 | 8 | 0 | 中断事件 | io | ||
test | RW | 7 | 4 | 0 | 测试寄存器 | o | ||
reg2 | 10 | ctrl | RW | 7 | 0 | 0 | 控制 | o |
reg3 | 11 | status | RO | 7 | 0 | 0 | 状态 | i |
Python代码:
#参数:
module_name = "excel2verilog"
globalName = "global_define"
#导入库文件
import openpyxl
import os
import time
import re
from openpyxl.styles import Font
def disp_task(cur_obj,sep="#",num=35):
disp_cur_obj = cur_obj.center(num,sep)
print()
print(disp_cur_obj)
disp_task("excel 表格操作",'#',40)
def displayExcel(sheet):
maxRowNum = sheet.max_row + 1
maxColNum = sheet.max_column + 1
for i in range(1,maxRowNum,1):# go through every other row:
if i == 1: #第一行
for j in range(1,maxColNum,1):
t = sheet.cell(row=i,column=j).value
t1 = str(t)
print(t1.center(20),end = '')
else: #非第一行
for j in range(1,maxColNum,1):
t = sheet.cell(row=i,column=j).value
t1 = str(t)
if (j<maxColNum-1):#非最后一行
print(t1.center(20),end = '')
else:
print('//',t1.ljust(20),end = '')
print(end='\n')
#检测文件是否存在
def detectFileExist(fp):
if os.path.exists(fp):
#删除文件
os.remove(fp)
print(f"文件‘{fp}’已经删除。")
else:
print(f"文件‘{fp}’不存在,无法删除。")
wb = openpyxl.load_workbook('./python_excise_u.xlsx')
type(wb)
#输出type类型
print("wb=",wb,"\n","type(wb)=",type(wb))
print("当前工作目录",os.getcwd())#需要系统函数sys支持
#工作表
#list_sheetnames = list(wb.sheetnames)
list_sheetnames = wb.sheetnames
#module_name = ''.join(list_sheetnames)
print("工作表:",list_sheetnames)
#生成一个test.v,其中写入的是将test.xlsx中的信息转化为verilog的代码框架
gen_file= os.getcwd()+"\\"+module_name+'.v'
globalFile = os.getcwd()+"\\"+globalName+'.vh'
#每次运行的时候检测test.v是否存在,如果存在则删除
detectFileExist(gen_file)
detectFileExist(globalFile)
print(''.join(module_name))#list ---> str
#打开excel名字为test的工作表
table= wb[list_sheetnames[0]] #open sheet by name
displayExcel(table)
#统计表格中的行数和列数
row_num = table.max_row
col_num = table.max_column
print("The excel max_row=%d;max_column=%d"%(row_num,col_num))
##定义列表变量
##地址
registerName = []
registerAddr = []
##端口名字 clk rst_n din dout
port_name=[]
##位宽 1 1 4 3
port_msb=[]##
port_lsb=[]##
##默认值
defaultValue = []
## 端口方向 input output inout
port_type=[]
regName = ""
regAddr = 0
for i in range(2,row_num+1):
print("regName:=",table.cell(row=i, column=1).value)
if( table.cell(row=i, column=1).value == None):
regName = regName
else:
regName = table.cell(row=i, column=1).value##excel中的第1列
regName = str(regName)
registerName.append(regName.upper())##添加到list
if(str(table.cell(row=i, column=2).value) == "None"):
regAddr = regAddr
else:
regAddr = hex(int( str(table.cell(row=i, column=2).value), 16))##excel中的第2列
regAddr.strip().lstrip("0x")##去除16进制的0x
#re.sub(r'^0x', '', regAddr)
registerAddr.append(regAddr)##添加到地址的list
port_name.append(table.cell(row=i, column=3).value)##excel中的第3列
port_type.append(table.cell(row=i,column=4).value)##excel中的第4列
port_msb.append(table.cell(row=i,column=5).value)##excel中的第5列
port_lsb.append(table.cell(row=i,column=6).value)##excel中的第6列
defaultValue.append(table.cell(row=i,column=7).value)##excel中的第7列
print("registerName:",registerName)
print("registerAddr:",registerAddr)
print("port_name:",port_name)
print("port_type:",port_type)
print("port_msb:",port_msb)
print("port_lsb:",port_lsb)
print("defaultValue:",defaultValue)
##保存宏定义
##verilog代码
includeGlobal = "`include \"global_define.vh\"\n"
apb_clk = "input wire i_clk ,\n"
apb_rst = "input wire i_rst_n ,\n"
apb_penable = "input wire i_penable ,\n"
apb_psel = "input wire i_psel ,\n"
apb_paddr = "input wire[31:0] i_paddr ,\n"
apb_pwrite = "input wire i_pwrite ,\n"
apb_pwdata = "input wire[31:0] i_pwdata ,\n"
apb_pready = "output wire o_pready ,\n"
apb_prdata = "output reg [31:0] o_prdata ,\n"
apb_pready_assign = "assign o_pready = 1'd1;\n"
##打开test.v并写入从excel信息对应的verilog代码
with open(gen_file,'a') as file_obj:
file_obj.write(includeGlobal)
file_obj.write('module '+module_name+'(\n')
file_obj.write(apb_clk)
file_obj.write(apb_rst)
file_obj.write(apb_psel)
file_obj.write(apb_penable)
file_obj.write(apb_paddr)
file_obj.write(apb_pwrite)
file_obj.write(apb_pwdata)
file_obj.write(apb_pready)
file_obj.write(apb_prdata)
for i in range(0,row_num-1,1):
#in/out
if(port_type[i] == "RO" or port_type[i] == "RC"):
port_str="input wire"
elif(port_type[i] == "RW"):
port_str="output reg "
#width
width_str='['+str(port_msb[i]-port_lsb[i])+':' + '0'+']'
print("width_str:",width_str)
if(i<row_num-2):
file_obj.write(port_str + width_str.ljust(8) + port_name[i].ljust(16)+',\n')
else:
file_obj.write(port_str + width_str.ljust(8) + port_name[i].ljust(16) + '\n );\n')
##RC
if(port_type[i] == "RC"):
port_str="output reg "
portNameTemp = port_name[i] + '_clr'
file_obj.write(port_str + ''.ljust(8) + portNameTemp.ljust(16) + ',\n')
##write
apbWrEn = "wire apb_write_en ;//apb write enable\n"
apbRdEn = "wire apb_read_en ;//apb read enable\n"
apbWrEnAssign = "assign apb_write_en = i_psel & i_penable & i_pwrite;\n"
apbRdEnAssign = "assign apb_write_en = (i_psel && i_penable==1'b0 && i_pwrite==1'b0) ? 1'b1 : 1'b0;\n"
always_clk = "always @(posedge i_clk or negedge i_rst_n) begin\n"
always_rst = " if(i_rst_n == 1'b0) begin\n"
with open(gen_file,'a') as file_obj:
file_obj.write(apbWrEn)
file_obj.write(apbRdEn)
file_obj.write(apb_pready_assign)
file_obj.write(apbWrEnAssign)
file_obj.write(apbRdEnAssign)
file_obj.write("\n//APB write\n")
file_obj.write(always_clk)
file_obj.write(always_rst)
variNameAssign= ""
##初始化
for i in range(0,row_num-1,1):
#in/out
if(port_type[i] == "RW" or port_type[i] == "WC"):
width_str=' ['+str(port_msb[i])+':' + str(port_lsb[i])+']'
widthStrOffset=' ['+str(port_msb[i]-port_lsb[i])+':' + '0]'
variNameAssign = " " + port_name[i].ljust(10) + widthStrOffset.ljust(10) + "<=" + str(defaultValue[i]).ljust(10) + ";\n"
file_obj.write(variNameAssign)
file_obj.write(" end\n")
file_obj.write(" else if(apb_write_en)begin\n")
file_obj.write(" case(i_paddr[31:0])\n")
##write assignment
registerNameTemp = 'reg'
for i in range(0,row_num-1,1):
#rw/wc
if(port_type[i] == "RW" or port_type[i] == "WC"):
width_str=' ['+str(port_msb[i])+':' + str(port_lsb[i])+']'
widthStrOffset=' ['+str(port_msb[i]-port_lsb[i])+':' + '0]'
variNameAssign = ' ' + port_name[i] + widthStrOffset.ljust(10) + "<=" + "i_pwdata" + width_str + ";\n"
if(registerName[i] == registerNameTemp):{#same reg
file_obj.write(variNameAssign)
}
else:#a new reg
file_obj.write(" end\n")
regDefine= " `" + registerName[i].ljust(10) + ": begin".ljust(10) + "//" +registerAddr[i] + "\n"# "\n"
file_obj.write(regDefine)
file_obj.write(variNameAssign)
else:
continue
registerNameTemp = registerName[i]
file_obj.write(" end\n")
file_obj.write(" default :begin end\n")
file_obj.write(" endcase\n")
file_obj.write(" end else begin\n")
##write clear
for i in range(0,row_num-1,1):
#in/out
if(port_type[i] == "WC"):
width_str=' ['+str(port_msb[i])+':' + str(port_lsb[i])+']'
widthStrOffset=' ['+str(port_msb[i]-port_lsb[i])+':' + '0]'
variNameAssign = " " + port_name[i] + widthStrOffset.ljust(10) + "<=" + "'d0" + ";\n"
file_obj.write(variNameAssign)
file_obj.write(" end\n")
file_obj.write("end\n")
##write clear
##read
oPrdataInit = " o_prdata[31:0] <= 32'h00;\n"
with open(gen_file,'a') as file_obj:
file_obj.write("\n//APB read\n")
file_obj.write(always_clk)
file_obj.write(always_rst)
file_obj.write(oPrdataInit)
file_obj.write(" end")
file_obj.write(" else if(apb_read_en)begin\n")
file_obj.write(" case(i_paddr[31:0])\n")
registerNameTemp = 'reg'
for i in range(0,row_num-1,1):
width_str=' ['+str(port_msb[i])+':' + str(port_lsb[i])+']'
widthStrOffset=' ['+str(port_msb[i]-port_lsb[i])+':' + '0]'
variNameAssign = " " + "o_prdata".ljust(10) + width_str.ljust(10) + "<=" + port_name[i].ljust(10) + widthStrOffset.ljust(10) + ";\n"
if(registerNameTemp == registerName[i]):
file_obj.write(variNameAssign)
else:
file_obj.write(" end\n")
file_obj.write(" `" + registerName[i].ljust(10) + ": begin".ljust(10)+"//" + registerAddr[i] + "\n")
file_obj.write(variNameAssign)
registerNameTemp = registerName[i]
file_obj.write(" end\n")
file_obj.write(" default:begin end\n")
file_obj.write(" endcase\n")
file_obj.write(" end\n")
file_obj.write(" else begin\n")
file_obj.write(" o_prdata[31:0] <= 32'h00;\n")
file_obj.write(" end\n")
file_obj.write("end\n")
variNameAssign= ""
##read clear
with open(gen_file,'a') as file_obj:
for i in range(0,row_num-1,1):
if(port_type[i] == "RC"):
#initial
file_obj.write("\n//Read clear" + port_name[i] + "\n")
file_obj.write(always_clk)
file_obj.write(always_rst)
file_obj.write(''.ljust(8) + port_name[i] + '_clr' + ' <= 1\'d0\n')
file_obj.write(" end\n")
#read
readClrAddr = " else if(apb_read_en &&" + "i_paddr[31:0] == `" + registerName[i] + ") begin\n"
file_obj.write(readClrAddr)
file_obj.write(''.ljust(8) + port_name[i] + '_clr' + ' <= 1\'d1\n')
#else
file_obj.write(" end else begin\n")
file_obj.write(''.ljust(8) + port_name[i] + '_clr' + ' <= 1\'d0\n')
file_obj.write(" end\n")
file_obj.write("end\n\n")
##end module
with open(gen_file,'a') as file_obj:
file_obj.write("endmodule\n")
##打开global.vh并写入从excel信息对应的verilog代码
with open(globalFile,'a') as file_obj:
temp = "reg"
for i in range(0,row_num-1,1):
#parameter
if(temp == registerName[i]):
print("same reg!")
else:
file_obj.write("`define "+registerName[i].ljust(10) + "\'h" + registerAddr[i].strip().lstrip("0x") +'\n')
temp = registerName[i]