一、点阵汉字生成
使用网站:https://www.zhetao.com/fontarray.html
在记事本中整理
二、工程建立
1. 引入ip核
建立过程参考:https://blog.csdn.net/YouthBlood9/article/details/125226768
2.代码实现
vga_param
`define vga_640_480//这里在你使用不同分辨率的时候要改变
//笔主因为老师要求不同分辨率,所以定义两种,其他可自行添加(根据前面的那个分辨率显示参数表格)
`ifdef vga_640_480
//执行操作A
`define H_Right_Border 8
`define H_Front_Porch 8
`define H_Sync_Time 96
`define H_Back_Porch 40
`define H_Left_Border 8
`define H_Data_Time 640
`define H_Total_Time 800
`define V_Bottom_Border 8
`define V_Front_Porch 2
`define V_Sync_Time 2
`define V_Back_Porch 25
`define V_Top_Border 8
`define V_Data_Time 480
`define V_Total_Time 525
`elsif vga_800_600
//执行操作B
`define H_Right_Border 0
`define H_Front_Border 40
`define H_Sync_Time 128
`define H_Back_Porch 88
`define H_Left_Border 0
`define H_Data_Time 800
`define H_Total_Time 1056
`define V_Bottom_Border 0
`define V_Front_Porch 1
`define V_Sync_Time 4
`define V_Back_Porch 23
`define V_Top_Border 0
`define V_Data_Time 600
`define V_Total_Time 628
`endif
vga_ctrl
`include "vga_param.v"
module vga_ctrl (
input wire clk , //vga clk 640*480 25.2MHz
input wire rst_n , //复位信号
input wire [23:0] data_disp , //
output reg [10:0] h_addr , //数据有效显示区域行地址
output reg [10:0] v_addr , //数据有效显示区域场地址
output reg vsync , //
output reg hsync , //
output reg [07:0] vga_r , //RGB三色
output reg [07:0] vga_g , //
output reg [07:0] vga_b , //
output reg vga_blk , //VGA 消隐信号
output wire vga_clk //
);
//参数定义
parameter H_SYNC_STA = 1 ,//行同步开始信号
H_SYNC_STO = `H_Sync_Time ,//行同步停止
H_Data_STA = `H_Sync_Time + `H_Back_Porch + `H_Left_Border,//行数据开始
H_Data_STO = `H_Sync_Time + `H_Back_Porch + `H_Left_Border + `H_Data_Time ,//行数据开始
V_SYNC_STA = 1 ,
V_SYNC_STO = `V_Sync_Time ,
V_Data_STA = `V_Sync_Time + `V_Back_Porch + `V_Top_Border,
V_Data_STO = `V_Sync_Time + `V_Back_Porch + `V_Top_Border + `V_Data_Time;
reg [11:00] cnt_h_addr ; //行地址计数器
wire add_h_addr ;
wire end_h_addr ;
reg [11:00] cnt_v_addr ; //场地址计数器
wire add_v_addr ;
wire end_v_addr ;
//行地址计数器
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
cnt_h_addr <= 12'd0;
end
else if (add_h_addr) begin
if (end_h_addr) begin
cnt_h_addr <= 12'd0;
end
else begin
cnt_h_addr <= cnt_h_addr + 12'd1;
end
end
else begin
cnt_h_addr <= cnt_h_addr;
end
end
assign add_h_addr = 1'b1;
assign end_h_addr = add_h_addr && cnt_h_addr >= `H_Total_Time - 1;
//场地址计数器
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
cnt_v_addr <= 12'd0;
end
else if (add_v_addr) begin
if (end_v_addr) begin
cnt_v_addr <= 12'd0;
end
else begin
cnt_v_addr <= cnt_v_addr + 12'd1;
end
end
else begin
cnt_v_addr <= cnt_v_addr;
end
end
assign add_v_addr = end_h_addr;
assign end_v_addr = add_v_addr && cnt_v_addr >= `V_Total_Time - 1;
//行场同步信号
//行同步信号
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
hsync <= 1'b1;
end
else if (cnt_h_addr == H_SYNC_STA - 1) begin
hsync <= 1'b0;
end
else if (cnt_h_addr == H_SYNC_STO - 1)begin
hsync <= 1'b1;
end
else begin
hsync <= hsync;
end
end
//场同步信号
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
vsync <= 1'b1;
end
else if (cnt_v_addr == V_SYNC_STA - 1) begin
vsync <= 1'b0;
end
else if (cnt_v_addr == V_SYNC_STO - 1)begin
vsync <= 1'b1;
end
else begin
vsync <= vsync;
end
end
assign vga_clk = ~clk;
//数据有效显示区域定义
//行
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
h_addr <= 11'd0;
end
else if ((cnt_h_addr >= H_Data_STA) && (cnt_h_addr <= H_Data_STO)) begin
h_addr <= cnt_h_addr - H_Data_STA;
end
else begin
h_addr <= 11'd0;
end
end
//场
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
v_addr <= 11'd0;
end
else if ((cnt_v_addr >= V_Data_STA) && (cnt_v_addr <= V_Data_STO)) begin
v_addr <= cnt_v_addr - V_Data_STA;
end
else begin
v_addr <= 11'd0;
end
end
//显示数据
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
vga_r <= 8'd0;
vga_g <= 8'd0;
vga_b <= 8'd0;
vga_blk <= 1'b0;
end
else if ((cnt_h_addr >= H_Data_STA -1) && (cnt_h_addr <= H_Data_STO - 1)
&& (cnt_v_addr >= V_Data_STA -1 ) && (cnt_v_addr <= V_Data_STO -1)) begin
vga_r = data_disp[23:16];//data_dis[23-:8]
vga_g = data_disp[15:08];//data_dis[15-:8]
vga_b = data_disp[07:00];//data_dis[07-:8]
vga_blk <= 1'b1;
end
else begin
vga_r <= 8'd0;
vga_g <= 8'd0;
vga_b <= 8'd0;
vga_blk <= 1'b0;
end
end
endmodule
data_gen
module data_gen (
input wire clk , //vga clk 640*480 25.2MHz
input wire rst_n , //复位信号
input wire [10:0] h_addr , //数据有效显示区域行地址
input wire [10:0] v_addr , //数据有效显示区域场地址
output reg [23:0] data_disp //数据
);
reg [ 223:0 ] char_line[ 15:0 ];//16*14个字符=224,224*16的字符存储区
//参数定义
parameter
BLACK = 24'h000000,
RED = 24'hFF0000,
GREEN = 24'h00FF00,
BLUE = 24'h0000FF,
YELLOW = 24'hFFFF00,
SKY_BULE= 24'h00FFFF,
PURPLE = 24'hFF00FF,
GRAY = 24'hC0C0C0,
WHITE = 24'hFFFFFF;
parameter
H_VLD = 640,
// H_VLD = 800,
V_VLD = 480,
// V_VLD = 600,
PIC_W = 224,
PIC_H = 16,
X_START = (H_VLD - PIC_W >> 1)-1,//正中间
Y_START = (V_VLD - PIC_H >> 1)- 1;
reg [10:00] pix_x,pix_y;//字符显示坐标
//显示区域
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
pix_x <= 11'd0;
pix_y <= 11'd0;
end
else if ((h_addr >= X_START - 1 && h_addr < X_START + PIC_W)
&& (v_addr >= Y_START && v_addr < Y_START + PIC_H)) begin
pix_x <= h_addr - X_START;
pix_y <= v_addr - Y_START;
end
else begin
pix_x = 11'h7FF;
pix_y = 11'h7FF;
end
end
//显示颜色
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
data_disp <= WHITE;
end
else if (pix_x != 11'h7FF && pix_y != 11'h7FF) begin
if (char_line[pix_y][223 - pix_x] == 1'b1) begin
data_disp <= PURPLE ;
end
else begin
data_disp <= WHITE ;
end
end
else
data_disp <= BLACK;
end
//初始化显示文字
always@( posedge clk or negedge rst_n ) begin
if ( !rst_n ) begin//将前面得到的点阵放在这里~
char_line[ 0 ] = 224'h10001082002000000000000000000000000000000000000000000000;
char_line[ 1 ] = 224'h11f8108200f000000000000000000000000000000000000000000000;
char_line[ 2 ] = 224'h101010841f0000000000000000000000000000000000000000000000;
char_line[ 3 ] = 224'h1020108810000000000018003c003c00080018007e00180018001800;
char_line[ 4 ] = 224'hfc40fbd0100000000000240042004200380024004200240024002400;
char_line[ 5 ] = 224'h10107f44400042000800420042000400420040004200420042004200;
char_line[ 6 ] = 224'h31fe3082108000000000400002004200080042000400420040004200;
char_line[ 7 ] = 224'hc10648545c000400080042004200080042005c004200020002002400;
char_line[ 8 ] = 224'h389239c41080000000005c000400020008004200080042005c004200;
char_line[ 9 ] = 224'h549255a8108000000000620018000400080042000800420062004200;
char_line[ 10 ] = 224'h54925290108000000000420004000800080042001000420042004200;
char_line[ 11 ] = 224'h11105154420042000800020042001000420042004200200020004200;
char_line[ 12 ] = 224'h91129282fffe00000000420002001000080042001000420042004200;
char_line[ 13 ] = 224'h11221482000000000000420042002000080042001000420042004200;
char_line[ 14 ] = 224'h12221084084000000000220042004200080024001000240022002400;
char_line[ 15 ] = 224'h144210881020000000001c003c007e003e001800100018001c001800;
char_line[ 15 ] = 224'h10941090201000000000000000000000000000000000000000000000;
char_line[ 15 ] = 224'h110810a0400800000000000000000000000000000000000000000000;
end
end
endmodule
vga_top
module vga_top (
input wire clk ,
input wire rst_n ,
output wire vsync , //
output wire hsync , //
output wire [07:00] vga_r , //RGB三色
output wire [07:00] vga_g , //
output wire [07:00] vga_b , //
output wire vga_blk , //
output wire vga_clk //
);
wire [23:00] data_disp;
wire vga_25;
wire vga_40;//60MHz
wire locked;
wire [10:00] h_addr;
wire [10:00] v_addr;
wire reset;
assign reset = rst_n & locked;
// pll u_pll (
// .areset ( !rst_n ),
// .inclk0 ( clk ),
// .c0 ( vga_25 )
// );
pll_25 pll_25_inst (
.areset ( ~rst_n ),
.inclk0 ( clk ),
.c0 ( vga_25 ),
.c1 ( vga_40 ),
.locked (locked)
);
data_gen u_data_gen(
.clk (vga_25 ), //vga clk 640*480 25.2MHz
.rst_n (reset ), //复位信号
.h_addr (h_addr ), //数据有效显示区域行地址
.v_addr (v_addr ), //数据有效显示区域场地址
.data_disp (data_disp) //
);
vga_ctrl u_vga_ctrl(
.clk (vga_25 ), //vga clk 640*480 25.2MHz
.rst_n (reset ), //复位信号
.data_disp (data_disp), //
.h_addr (h_addr ), //数据有效显示区域行地址
.v_addr (v_addr ), //数据有效显示区域场地址
.vsync (vsync ), //
.hsync (hsync ), //
.vga_r (vga_r ), //RGB三色
.vga_g (vga_g ), //
.vga_b (vga_b ), //
.vga_blk (vga_blk ), //
.vga_clk (vga_clk ) //
);
endmodule
vga_tb
module vga_top (
input wire clk ,
input wire rst_n ,
output wire vsync , //
output wire hsync , //
output wire [07:00] vga_r , //RGB三色
output wire [07:00] vga_g , //
output wire [07:00] vga_b , //
output wire vga_blk , //
output wire vga_clk //
);
wire [23:00] data_disp;
wire vga_25;//25MHz
wire vga_40;//40MHz
wire locked;
wire [10:00] h_addr;
wire [10:00] v_addr;
wire reset;
assign reset = rst_n & locked;
pll_25 pll_25_inst (
.areset ( ~rst_n ),
.inclk0 ( clk ),
.c0 ( vga_25 ),
.c1 ( vga_40 ),
.locked (locked)
);
data_gen u_data_gen(
.clk (vga_25 ), //vga clk 640*480 25.2MHz
.rst_n (reset ), //复位信号
.h_addr (h_addr ), //数据有效显示区域行地址
.v_addr (v_addr ), //数据有效显示区域场地址
.data_disp (data_disp) //
);
vga_ctrl u_vga_ctrl(
.clk (vga_25 ), //vga clk 640*480 25.2MHz
.rst_n (reset ), //复位信号
.data_disp (data_disp), //
.h_addr (h_addr ), //数据有效显示区域行地址
.v_addr (v_addr ), //数据有效显示区域场地址
.vsync (vsync ), //
.hsync (hsync ), //
.vga_r (vga_r ), //RGB三色
.vga_g (vga_g ), //
.vga_b (vga_b ), //
.vga_blk (vga_blk ), //
.vga_clk (vga_clk ) //
);
endmodule
上板验证:
vga显示彩条
代码实现
data_gen
module data_gen (
input wire clk , //vga clk 640*480 25.2MHz
input wire rst_n , //复位信号
input wire [10:0] h_addr , //数据有效显示区域行地址
input wire [10:0] v_addr , //数据有效显示区域场地址
output reg [23:0] data_disp //
);
//参数定义
parameter
BLACK = 24'h000000,
RED = 24'hFF0000,
GREEN = 24'h00FF00,
BLUE = 24'h0000FF,
YELLOW = 24'hFFFF00,
SKY_BULE= 24'h00FFFF,
PURPLE = 24'hFF00FF,
GRAY = 24'hC0C0C0,
WHITE = 24'hFFFFFF;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
data_disp <= WHITE;
end
else begin//彩条
case (h_addr)
0 : data_disp <= BLACK ;
80 : data_disp <= RED ;
160 : data_disp <= GREEN ;
240 : data_disp <= BLUE ;
320 : data_disp <= YELLOW ;
400 : data_disp <= SKY_BULE ;
480 : data_disp <= PURPLE ;
560 : data_disp <= GRAY ;
default: data_disp <= data_disp ;
endcase
end
end
endmodule
上板验证
参考链接:https://blog.csdn.net/qq_45659777/article/details/124834294