FPGA 做 VGA 显示,英文字符大家基本都会——8×16 点阵,查个 ROM 就完事了。但一旦要显示汉字,问题立刻变多:字库怎么建、存多少 BRAM、刷新时序怎么配合、滚动显示怎么做。下面把这几个核心点拆清楚,把"汉字上屏"从模糊印象变成可落地的步骤。
### FPGA VGA 显示汉字,点阵字库到底怎么存、怎么调用?
核心思路一句话:把每个汉字拆成点阵矩阵,灌进 ROM,VGA 逐行扫描时按像素坐标查表输出。
字库存储与地址计算。 16×16 汉字点阵,每个字占 16×16 = 256 bit,即 32 字节。假设一屏要显示 12 行 × 4 列共 48 个常用字,ROM 容量 = 48 × 32 = 1536 字节,一片 18Kbit BRAM 绑绑有余。地址公式:addr = char_index × 32 + row × 4 + byte_col,其中 char_index 是该字在字库中的序号,row 为当前扫描到该字内部的第几行(0\~15),byte_col 为行内第几个字节(0\~3)。
逐行扫描出像素。 VGA 800×480@60Hz 的时序参数是固定的,你只需关注有效显示区。每一行扫描到汉字所在区域时,用当前 (x, y) 坐标算出它落在第几个字的第几行第几列,再去 ROM 读对应 bit。一个 16×16 的字水平占 16 px、垂直占 16 px,800 px 宽一屏理论上排 50 列,留边距后实际约 40 列。
省带宽技巧。 ROM 一次出 8 bit(覆盖同一行连续 8 个像素),用移位寄存器把 8 个像素"摊开"到 8 个像素时钟周期里逐位送出。这样 ROM 读一次供 8 个像素用,BRAM 读带宽直接砍到 1/8,时序余量非常充裕。
### 显示汉字和显示英文字符,在 VGA 时序上有啥区别?
VGA 的同步时序(消隐、前肩、后肩)跟显示内容无关,800×480@60Hz 就是那套固定参数。区别全在有效区内部的像素驱动逻辑:
字模尺寸:英文 8×16,汉字最少 16×16,追求清晰度常用 32×32。字模越大,一屏可排字数越少,但笔画辨识度更高。
ROM 容量差 4 倍:英文 95 个可打印字符 × 16 B ≈ 1.5 KB;汉字放 200 个常用字 × 64 B(32×32)= 12.8 KB。BRAM 规划要提前算好,别写代码到一半发现资源不够。
滚动与换行:英文逐字符步进 8 px,汉字步进 16 或 32 px。做 60 帧无撕裂滚动,需要双缓冲——两块 BRAM 交替读写,屏幕刷新时另一块在后台改内容,否则会出现"半帧拼接"的撕裂现象。
字库生成:汉字点阵不能手写,通常用工具把 TTF 字体转成 16×16 或 32×32 的 BMP 点阵,再导出 hex 文件灌进 ROM。英文则可以直接查标准 8×16 ASCII 码表,省掉这一步。
VGA 显示汉字,本质就是"坐标查表 + 逐行出像素":字库存 ROM、时序套标准、滚动靠双缓冲,三步走通。
思考题:把字模从 16×16 升到 32×32,ROM 容量翻倍,水平方向一屏只能排 25 个字——你会缩小一屏字数,还是换用 DDR 存字库?各有什么代价?
如果你正在做课程项目或毕设,卡在"字库怎么建、BRAM 怎么分、滚动画面为什么闪"这些细节上,可以点官网右下角的会话窗口,跟宸极教育的 FPGA 课程顾问聊聊。我们会根据你的基础——纯新手、会 Verilog 但没碰过 VGA、还是想直接上 32×32 无撕裂滚动——推荐对应的实战模块和练习路径,不用从零瞎摸索。
未经许可,禁止转载!