如何实现VBA宏生成的VHDL代码冒号列对齐排版
VBA生成VHDL常量冒号固定列对齐方案
核心逻辑很简单:不要边扫描表格边写文件,先把所有寄存器条目收集全,算出最长寄存器名的长度,给短名称后面补空格把冒号顶到统一位置就行,VHDL编辑器默认用等宽字体,只要字符数凑齐,对齐不会歪。
具体实现步骤
- 第一遍扫描表格:把所有有效寄存器的名称、地址、默认值暂存到集合/数组里,同时记录所有寄存器名的最大字符长度。
- 确定对齐位置:取「最长寄存器名长度 + 2~3个空格的余量」作为冒号的对齐基准,留空当避免最长名称和冒号贴太近影响可读性。
- 第二遍拼接输出:逐行拼代码的时候,给长度不足的寄存器名后面补对应数量的空格,再接冒号和后续的常量定义内容。
- 如果需要连后面的赋值符
:=也对齐,用同样的逻辑,再统计一次冒号到赋值符之间内容的最大长度,二次补空格即可。
核心实现代码(VBA)
Sub OutputAlignedVhdlConst() Dim regList As New Collection Dim ws As Worksheet Dim lastRow As Long, i As Long Dim maxNameLen As Long, padSpaceCount As Long Dim outputStr As String ' 以下参数按你自己的表格结构修改 Set ws = ThisWorkbook.Sheets("寄存器映射表") Const typeCol As String = "B" ' 标记条目类型的列 Const nameCol As String = "C" ' 寄存器名称列 Const defValCol As String = "E" ' 默认值列 Const startRow As Long = 2 ' 数据起始行(跳过表头) lastRow = ws.Cells(ws.Rows.Count, nameCol).End(xlUp).Row maxNameLen = 0 ' 第一轮扫描:收集条目+统计最长名称 For i = startRow To lastRow If VBA.UCase(ws.Cells(i, typeCol).Value) = "REGISTER" Then Dim item As Object Set item = CreateObject("Scripting.Dictionary") item("name") = Trim(ws.Cells(i, nameCol).Value) item("defVal") = Trim(ws.Cells(i, defValCol).Value) regList.Add item If Len(item("name")) > maxNameLen Then maxNameLen = Len(item("name")) End If Next i ' 计算补空数量,留3个空格余量 padSpaceCount = maxNameLen + 3 ' 第二轮拼接对齐后的代码 outputStr = "" For Each item In regList Dim prefix As String prefix = "constant " & item("name") ' 补空格到固定长度 prefix = prefix & Space(padSpaceCount - Len(item("name"))) ' 拼接剩余VHDL语句,按你自己的位宽、地址定义改格式 outputStr = outputStr & prefix & ": std_logic_vector(31 downto 0) := x""" & item("defVal") & """;" & vbCrLf Next item ' 写入目标vhdl文件 Open ThisWorkbook.Path & "\reg_define.vhd" For Output As #1 Print #1, outputStr; Close #1 End Sub
效果参考
对齐前(排版错乱)
constant REG_CTRL : std_logic_vector(31 downto 0) := x"00000000"; constant REG_STATUS_FIFO : std_logic_vector(31 downto 0) := x"00000001"; constant REG_BAUD_CFG : std_logic_vector(31 downto 0) := x"00000002";
对齐后(冒号统一列)
constant REG_CTRL : std_logic_vector(31 downto 0) := x"00000000"; constant REG_STATUS_FIFO : std_logic_vector(31 downto 0) := x"00000001"; constant REG_BAUD_CFG : std_logic_vector(31 downto 0) := x"00000002";
注意事项
- 所有代码字符保持半角输入,不要混全角空格/符号,不然等宽字体下对齐会偏。
- 如果常量类型不统一(比如有1位的std_logic、有整数类型常量),要对齐
:=的话就多做一轮长度统计,在类型后面补空格即可,逻辑和对齐冒号完全一致。 - 不要用Tab键补位,不同编辑器Tab宽度设置不一样,用半角空格补位兼容性最好。
内容的提问来源于stack exchange,提问作者julien1h
相关产品推荐
相关产品推荐

