前言
小时候记得excel里有一个神秘的赛车游戏,发现excel原来并不简单啊;
之前我哥跟我讲excel可能是最牛逼的编程软件,但是当时我没信,现在我有点信了;
工作后发现很多代码原来并不需要写,通过excel、xml直接生成还是爽爽的;
最好的是,自带的编译器自动补全自动大小写转换自动联想比平时用的IDE舒服多了;
所以说啊,学一学VBA还是挺有意思的,你也不知道啥时候就用得上;
作为我写的第一个excel vba demo,必须好好记录下。
目标
通过excel添加信号,并生成Verilog module代码,每个sheet作为一个模块,最终的实现的效果如下:
1.点击添加信号;
2.输入信号名称;
3.输入信号位宽,默认为1;
4.输入信号类型,默认wires;
5.输入是否接口,默认no;
6.完成一个信号输入后,可以继续添加;单一信号输入途中选择取消,则推出输入;
7.点击“生成代码”,直接生成module rtl,除了对齐失败以外,可以说非常完美;
实现
列举一下用到的sub/function;
信号输入
1. Option Explicit 2. 3. Dim sigName As String 4. Dim sigWidh As String 5. Dim sigType As String 6. Dim sigPort As String 7. 8. Public Type sigInfo 9. name As String 10. widh As Integer 11. type As String 12. port As String 13. End Type
全局定义,由于开始没考虑清楚,有重复定义之嫌;全局变量用来输入和获取信号信息;
1. Private Function gainLastRow() As Integer 2. 3. Dim lastRow As Integer 4. 5. lastRow = ActiveSheet.UsedRange.Rows.Count 6. gainLastRow = ActiveSheet.UsedRange.Rows(lastRow).Row + 1 7. 'Debug.Print gainLastRow 8. 9. End Function
获取当前sheet最后一行位置,之后添加信号时默认向最后添加;
1. Private Function gainSigIn() As Boolean 2. 3. sigName = InputBox(prompt:="信号名称") 4. If sigName = "" Then 5. gainSigIn = False 6. Exit Function 7. End If 8. 9. 10. sigWidh = InputBox(prompt:="信号位宽", Default:="1") 11. If sigWidh = "" Then 12. gainSigIn = False 13. Exit Function 14. End If 15. 16. sigType = InputBox(prompt:="信号类型reg/wire??", Default:="wire") 17. If sigType = "" Then 18. gainSigIn = False 19. Exit Function 20. End If 21. 22. sigPort = InputBox(prompt:="接口属性no/input/output/inout??", Default:="no") 23. If sigPort = "" Then 24. gainSigIn = False 25. Exit Function 26. End If 27. 28. gainSigIn = True 29. 30. End Function
通过inputbox函数获取键入的信号信息;
1. Public Sub mainAddSig() 2. 3. Dim addRow As Integer 4. 5. Do 6. If gainSigIn() = True Then 7. 'Debug.Print "@@@@@@@" 8. addRow = gainLastRow() 9. With ActiveSheet 10. .Cells(addRow, 1).Value = sigName 11. .Cells(addRow, 2).Value = sigWidh 12. .Cells(addRow, 3).Value = sigType 13. .Cells(addRow, 4).Value = sigPort 14. End With 15. Else 16. Exit Sub 17. End If 18. Loop Until MsgBox("是否继续输入", vbOKCancel) <> vbOK 19. 20. End Sub
“添加信号”按钮绑定sub,将获取到的信号信息写入单元格最后一行后面,写入完成后询问是否继续输入;
生成代码
1. Private Function gainOrgLoc() As Integer 2. 3. Dim keyCell As Range 4. 5. Cells(1, 1).Select 6. 7. 'Set keyCell = ActiveSheet.UsedRange.Find(What:="???????", After:=ActiveCell, LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=True, SearchFormat:=False) 8. Set keyCell = Cells.Find(What:="???????", After:=ActiveCell, LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=True, SearchFormat:=False) 9. 10. If keyCell Is Nothing Then 11. gainOrgLoc = -1 12. Else 13. gainOrgLoc = keyCell.Row 14. 'Debug.Print gainOrgLoc 15. End If 16. 17. End Function
以左上角(1,1)坐标为起始,寻找标志“信号名称”,其下一行到最后一行为信号定义区间;
1. Private Function gainSigInfo(setRow As Integer) As sigInfo 2. 3. With ActiveSheet 4. gainSigInfo.name = .Cells(setRow, 1) 5. gainSigInfo.widh = .Cells(setRow, 2) 6. gainSigInfo.type = .Cells(setRow, 3) 7. gainSigInfo.port = .Cells(setRow, 4) 8. End With 9. 10. End Function
获取某一行信号信息;
1. Public Sub genRtlCode() 2. 3. Dim inputArray As New Collection 4. Dim outputArray As New Collection 5. Dim inoutArray As New Collection 6. Dim wireArray As New Collection 7. Dim regArray As New Collection 8. 9. Dim startRow As Integer 10. Dim sig As sigInfo 11. Dim ss As New Collection 12. 13. Dim i As Integer 14. Dim s As String 15. 16. startRow = gainOrgLoc() + 1 17. 18. For i = startRow To gainLastRow 19. sig = gainSigInfo(i) 20. If sig.name <> "" Then 21. If sig.port = "input" Then 22. inputArray.Add (" input " & sig.type & " [" & sig.widh & " -1:0] " & sig.name & ";") 23. 'Debug.Print " input " & sig.type & " [" & sig.widh & " -1:0] " & sig.name & ";" 24. ElseIf sig.port = "output" Then 25. outputArray.Add (" output " & sig.type & " [" & sig.widh & " -1:0] " & sig.name & ";") 26. 'Debug.Print " output " & sig.type & " [" & sig.widh & " -1:0] " & sig.name & ";" 27. ElseIf sig.port = "inout" Then 28. inoutArray.Add (" inout " & sig.type & " [" & sig.widh & " -1:0] " & sig.name & ";") 29. ElseIf sig.port = "no" And sig.type = "wire" Then 30. wireArray.Add (" wire " & " [" & sig.widh & " -1:0] " & sig.name & ";") 31. 'Debug.Print " wire " & " [" & sig.widh & " -1:0] " & sig.name & ";" 32. ElseIf sig.port = "no" And sig.type = "reg" Then 33. regArray.Add (" reg " & " [" & sig.widh & " -1:0] " & sig.name & ";") 34. 'Debug.Print " reg " & " [" & sig.widh & " -1:0] " & sig.name & ";" 35. End If 36. End If 37. Next 38. 39. Open "C:\Users\gaoji\Desktop\RISC_SPM\gen.sv" For Output As #1 40. Print #1, "module " & ActiveSheet.name & "(" 41. 42. For i = 1 To inputArray.Count 43. s = inputArray.Item(i) 44. Print #1, s 45. Next 46. For i = 1 To outputArray.Count 47. s = outputArray.Item(i) 48. Print #1, s 49. Next 50. For i = 1 To inoutArray.Count 51. s = inoutArray.Item(i) 52. Print #1, s 53. Next 54. 55. Print #1, ");" 56. 57. For i = 1 To regArray.Count 58. s = regArray.Item(i) 59. Print #1, s 60. Next 61. For i = 1 To wireArray.Count 62. s = wireArray.Item(i) 63. Print #1, s 64. Next 65. 66. Print #1, "endmodule" 67. 68. Close #1 69. 70. 71. End Sub
从起始行到最终行,获取每一行的信号信息并根据属性组织代码放入不同的collection中;
之后将组织好的代码写入文件中。