基于FPGA的信号波形发生器,通过二进制进行显示汉字,可以显示任意汉字,需要的可以来哟!通过quarter9.0进行编程仿真,可以仿真出汉字模型!
最近在实验室折腾FPGA的时候,发现个挺有意思的玩法——用信号波形发生器在示波器上直接显示汉字。这可比普通数字管显示酷多了,关键还能自定义显示内容。今天就给大家掰扯掰扯怎么用Verilog在FPGA上实现这个骚操作。
先说说核心思路。汉字显示本质上就是把字形转换成坐标点的亮灭状态,这个咱们可以用16x16点阵来实现。每个汉字对应256个二进制位,1表示点亮,0就是熄灭。比如"汉"字的字模数据大概是这样的:
parameter [255:0] HANZI_HAN = { 8'h00,8'h20,8'h10,8'h0C,8'h43,8'h80,8'h60,8'h1E, 8'h01,8'h01,8'h7F,8'h01,8'h01,8'h01,8'h01,8'h01, 8'h00,8'h00,8'h00,8'hFE,8'h00,8'h00,8'h00,8'h00, 8'h40,8'h20,8'h10,8'h0C,8'h03,8'h00,8'h00,8'h00 };这个数据块看着像天书?其实每个十六进制数对应一行8个像素的状态。比如0x7F转二进制是01111111,对应中间六个像素点亮,两边熄灭。把这些数据存到FPGA的ROM里,就相当于建了个汉字库。
基于FPGA的信号波形发生器,通过二进制进行显示汉字,可以显示任意汉字,需要的可以来哟!通过quarter9.0进行编程仿真,可以仿真出汉字模型!
接下来要搞个扫描控制器,这才是重头戏。核心代码大概长这样:
module display_controller( input clk, output reg [15:0] row, output reg [15:0] col ); reg [4:0] cnt = 0; always @(posedge clk) begin cnt <= cnt + 1; // 行扫描 row <= 16'h0001 << cnt[3:0]; // 列数据输出 col <= char_data[cnt]; if(cnt == 31) cnt <= 0; end endmodule这个模块每16个时钟周期完成一次全屏刷新。cnt既控制行扫描位置,又作为字模数据的索引。行信号像探照灯一样逐行扫描,列数据同步输出对应行的像素状态。实际用示波器看的话,X轴接行扫描信号,Y轴接列数据,就能在屏幕上拼出完整汉字。
仿真的时候用Quartus自带的SignalTap抓波形特别有意思。把行、列信号设置成模拟波形显示,直接就能看到汉字轮廓。比如设置成"电"字的时候,波形图会呈现出明显的"闪电"形状的跳变沿。
最后说下字库扩展的骚操作。不想手动敲二进制数据的,可以用UCDOS的HZK16字库,直接转成.mif文件导入FPGA。Python写个转换脚本就搞定:
with open('hzk16', 'rb') as f: data = f.read() offset = (94*(qh-1)+(wh-1))*32 print(''.join([f'{x:02X}' for x in data[offset:offset+32]]))这个方案实测在Cyclone IV上跑50MHz时钟完全无压力,动态显示效果比LCD还流畅。想要显示生僻字?直接把转换后的数据往ROM里一扔,想显示什么就显示什么。手头有FPGA开发板的同学可以试试,示波器上跳出汉字的那一刻绝对有惊喜。