导读
VGA (Video Graphics Array) 即视频图形阵列,是IBM于1987年随PS/2机(PersonalSystem 2)一起推出的使用模拟信号的一种视频传输标准。这个标准对于现今的个人电脑市场已经十分过时。但在当时具有分辨率高、显示速率快、颜色丰富等优点,在彩色显示器领域取得了广泛的应用,是众多制造商所共同支持的一个低标准。
LCD ( Liquid Crystal Display 的简称)液晶显示器。LCD 的构造是在两片平行的玻璃基板当中放置液晶盒,下基板玻璃上设置TFT(薄膜晶体管),上基板玻璃上设置彩色滤光片,通过TFT上的信号与电压改变来控制液晶分子的转动方向,从而达到控制每个像素点偏振光出射与否而达到显示目的。按照背光源的不同,LCD可以分为CCFL显示器和LED显示器两种。LCD已经替代CRT成为主流,价格也已经下降了很多,并已充分普及。
在之前的文章中介绍了如何获取、处理摄像头提供的视频信号,在实际应用中还需要将经过处理的信号显示在显示器上。这个过程与信号处理中的过程上是相反的,将数字信号按照电视信号的制式组成合乎时序、格式要求的信号,并加入用于控制的各种同步信号。本篇将通过 FPGA实现一个 VGA/LCD 显示控制器的实例,并详细介绍实现过程。
四、程序的仿真与测试
为了检验程序是否实现预先设定的功能,需要编写仿真程序。仿真程序的主要代码如下:
module test;
//寄存器
reg clk;
reg rst;
//参数
parameter LINE_FIFO_AWIDTH = 7;
//wire 申明
wire int;
wire [31:0] wb_addr_o;
wire [31:0] wb_data_i;
wire [31:0] wb_data_o;
wire [3:0] wb_sel_o;
wire wb_we_o;
wire wb_stb_o;
wire wb_cyc_o;
wire [2:0] wb_cti_o;
wire [1:0] wb_bte_o;
wire wb_ack_i;
wire wb_err_i;
wire [31:0] wb_addr_i;
wire [31:0] wbm_data_i;
wire [3:0] wb_sel_i;
wire wb_we_i;
wire wb_stb_i;
wire wb_cyc_i;
wire wb_ack_o;
wire wb_rty_o;
wire wb_err_o;
reg pclk_i;
wire pclk;
wire hsync;
wire vsync;
wire csync;
wire blanc;
wire [7:0] red;
wire [7:0] green;
wire [7:0] blue;
wire dvi_pclk_p_o;
wire dvi_pclk_m_o;
wire dvi_hsync_o;
wire dvi_vsync_o;
wire dvi_de_o;
wire [11:0] dvi_d_o;
wire vga_stb_i;
wire clut_stb_i;
reg scen;
// 测试程序变量
integer wd_cnt;
integer error_cnt;
reg [31:0] data;
reg [31:0] pattern;
reg int_warn;
integer n;
integer mode;
reg [7:0] thsync, thgdel;
reg [15:0] thgate, thlen;
reg [7:0] tvsync, tvgdel;
reg [15:0] tvgate, tvlen;
reg hpol;
reg vpol;
reg cpol;
reg bpol;
integer p, l;
reg [31:0] pn;
reg [31:0] pra, paa, tmp;
reg [23:0] pd;
reg [1:0] cd;
reg pc;
reg [31:0] vbase;
reg [31:0] cbase;
reg [31:0] vbara;
reg [31:0] vbarb;
reg [7:0] bank;
// 常量定义
`define CTRL 32'h0000_0000
`define STAT 32'h0000_0004
`define HTIM 32'h0000_0008
`define VTIM 32'h0000_000c
`define HVLEN 32'h0000_0010
`define VBARA 32'h0000_0014
`define VBARB 32'h0000_0018
`define USE_VC 1
parameter PCLK_C = 20;
//测试内容
initial
begin
$timeformat (-9, 1, " ns", 12);
$display("
");
$display("******************************************************");
$display("*VGA/LCD Controller Simulation started ... *");
$display("******************************************************");
$display("
");
`ifdef WAVES
$shm_open("waves");
$shm_probe("AS",test,"AS");
$display("INFO: Signal dump enabled ...
");
`endif
scen = 0;
error_cnt = 0;
clk = 0;
pclk_i = 0;
rst = 0;
int_warn=1;
repeat(20) @(posedge clk);
rst = 1;
repeat(20) @(posedge clk);
if(0)
begin
end
else
if(1)
begin
`ifdef VGA_12BIT_DVI
dvi_pd_test;
`endif
end
else
begin
// 测试区域
$display("
");
$display("*****************************************************");
$display("*** XXX Test ***");
$display("*****************************************************
");
s0.fill_mem(1);
repeat(10) @(posedge clk);
//参数设置
vbara = 32'h0000_0000;
vbarb = 32'h0001_0000;
m0.wb_wr1( `VBARA, 4'hf, vbara );
m0.wb_wr1( `VBARB, 4'hf, vbarb );
thsync = 0;
thgdel = 0;
thgate = 340;
thlen = 345;
tvsync = 0;
tvgdel = 0;
tvgate = 240;
tvlen = 245;
/*
thsync = 0;
thgdel = 0;
thgate = 63;
thlen = 70;
tvsync = 0;
tvgdel = 0;
tvgate = 32;
tvlen = 36;
*/
hpol = 0;
vpol = 0;
cpol = 0;
bpol = 0;
m0.wb_wr1( `HTIM, 4'hf, {thsync, thgdel, thgate} );
m0.wb_wr1( `VTIM, 4'hf, {tvsync, tvgdel, tvgate} );
m0.wb_wr1( `HVLEN, 4'hf, {thlen, tvlen} );
mode = 2;
for(bank=0;bank<3;bank=bank + 1)
begin
case(mode)
0:
begin
cd = 2'h2;
pc = 1'b0;
end
1:
begin
cd = 2'h0;
pc = 1'b0;
end
2:
begin
cd = 2'h0;
pc = 1'b1;
end
3:
begin
cd = 2'h1;
pc = 1'b0;
end
endcase
m0.wb_wr1( `CTRL, 4'hf, {
16'h0, // Reserved
bpol, cpol,
vpol, hpol,
pc, // 1'b0, // PC
cd, // 2'h2, // CD
2'h0, // VBL
1'b0, // Reserved
1'b1, // CBSWE
1'b1, // VBSWE
1'b0, // BSIE
1'b0, // HIE
1'b0, // VIE
1'b1 // Video Enable
});
$display("Mode: %0d Screen: %0d", mode, bank);
//repeat(2) @(posedge vsync);
@(posedge vsync);
// 每一行数据
for(l=0;l9000)
begin
$display("
*************************************
");
$display("ERROR: Watch Dog Counter Expired
");
$display("*************************************
");
$finish;
end
always @(posedge int)
if(int_warn)
begin
$display("
*************************************
");
$display("WARNING: Recieved Interrupt (%0t)", $time);
$display("*************************************
");
end
always #2.5 clk = ~clk;
always #(PCLK_C/2) pclk_i = ~pclk_i;
//模块原型
vga_enh_top #(1'b0, LINE_FIFO_AWIDTH) u0 (
.wb_clk_i ( clk ),
.wb_rst_i ( 1'b0 ),
.rst_i ( rst ),
.wb_inta_o ( int ),
//从信号
.wbs_adr_i ( wb_addr_i[11:0] ),
.wbs_dat_i ( wb_data_i ),
.wbs_dat_o ( wb_data_o ),
.wbs_sel_i ( wb_sel_i ),
.wbs_we_i ( wb_we_i ),
.wbs_stb_i ( wb_stb_i ),
.wbs_cyc_i ( wb_cyc_i ),
.wbs_ack_o ( wb_ack_o ),
.wbs_rty_o ( wb_rty_o ),
.wbs_err_o ( wb_err_o ),
//主信号
.wbm_adr_o ( wb_addr_o[31:0] ),
.wbm_dat_i ( wbm_data_i ),
.wbm_sel_o ( wb_sel_o ),
.wbm_we_o ( wb_we_o ),
.wbm_stb_o ( wb_stb_o ),
.wbm_cyc_o ( wb_cyc_o ),
.wbm_cti_o ( wb_cti_o ),
.wbm_bte_o ( wb_bte_o ),
.wbm_ack_i ( wb_ack_i ),
.wbm_err_i ( wb_err_i ),
//VGA 信号
.clk_p_i ( pclk_i ),
`ifdef VGA_12BIT_DVI
.dvi_pclk_p_o ( dvi_pclk_p_o ),
.dvi_pclk_m_o ( dvi_pclk_m_o ),
.dvi_hsync_o ( dvi_hsync_o ),
.dvi_vsync_o ( dvi_vsync_o ),
.dvi_de_o ( dvi_de_o ),
.dvi_d_o ( dvi_d_o ),
`endif
.clk_p_o ( pclk ),
.hsync_pad_o ( hsync ),
.vsync_pad_o ( vsync ),
.csync_pad_o ( csync ),
.blank_pad_o ( blanc ),
.r_pad_o ( red ),
.g_pad_o ( green ),
.b_pad_o ( blue )
);
wb_mast m0( .clk( clk ),
.rst( rst ),
.adr( wb_addr_i ),
.din( wb_data_o ),
.dout( wb_data_i ),
.cyc( wb_cyc_i ),
.stb( wb_stb_i ),
.sel( wb_sel_i ),
.we( wb_we_i ),
.ack( wb_ack_o ),
.err( wb_err_o ),
.rty( 1'b0 )
);
wb_slv #(24) s0(.clk( clk ),
.rst( rst ),
.adr( {1'b0, wb_addr_o[30:0]} ),
.din( 32'h0 ),
.dout( wbm_data_i ),
.cyc( wb_cyc_o ),
.stb( wb_stb_o ),
.sel( wb_sel_o ),
.we( wb_we_o ),
.ack( wb_ack_i ),
.err( wb_err_i ),
.rty( )
);
`include "tests.v"
endmodule
五、总结
本篇介绍了一个 VGA/LCD 显示控制器的实例。首先介绍了 VGA/LCD 显示的相关知识,然后介绍了程序的主要结构和主要功能模块的实现过程。最后用一个测试程序验证程序的功能是否满足要求。本章为各位大侠设计自己的 VGA/LCD 显示控制器提供了一个可以使用的方案。
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !