FPGA-基于ROM的静态图片的读取
模块设计思路:
1、 ROM ip核
2、qvga屏幕显示驱动
module qvga_controller(clk,rst_n,lcd_light_en,lcd_clk,lcd_hsy,lcd_vsy,lcd_r,lcd_g,lcd_b,rom_db,rom_ab
);
input clk;
input rst_n;
input [15:0] rom_db;
output [13:0]rom_ab;
output lcd_light_en;
output lcd_clk;
output reg lcd_hsy;
output reg lcd_vsy;
output [4:0] lcd_r;
output [5:0] lcd_g;
output [4:0] lcd_b;
parameter HSY_TH=9'D408-1'D1;//周期
parameter HSY_THS=9'D30 ;//脉冲宽度
parameter HSY_THB=9'D38 ;//后沿
parameter HSY_TEP=9'D320 ;//显示周期
parameter HSY_THE=9'D68 ;//同步周期
parameter HSY_THF=9'D20 ;//前沿
parameter VSY_TV=9'D262-1'D1;//周期
parameter VSY_TVS=9'D3 ;//脉冲宽度
parameter VSY_TVB=9'D15 ;//后沿
parameter VSY_TVD=9'D240 ;//显示周期
parameter VSY_TVF=9'D4 ;//前沿
//lcd背光常开
assign lcd_light_en=1'b1;
//配置驱动时钟6.25mHz
reg [1:0] lcd_cnt;
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
lcd_cnt<=1'b0;
end
else begin
lcd_cnt<=lcd_cnt+1'b1;
end
end
assign lcd_clk=lcd_cnt[1];
wire dchange ={lcd_cnt==2'd2};
//X和Y轴计数器
reg[8:0] xcnt;
reg[8:0] ycnt;
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
xcnt<=1'b0;
end
else if(dchange==1'b1)begin
if(xcnt==HSY_TH)begin
xcnt<=1'b0;
end
else begin
xcnt<=xcnt+1'b1;
end
end
else;
end
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
ycnt<=1'b0;
end
else if(dchange&&xcnt==HSY_TH)begin
if(ycnt==VSY_TV)begin
ycnt<=1'b0;
end
else begin
ycnt<=ycnt+1'b1;
end
end
else begin
ycnt<=ycnt;
end
end
//lcd显示的有效区域
reg valid;
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
valid<=1'b0;
end
else if(ycnt>=(VSY_TVS+VSY_TVB)&&ycnt<(VSY_TVS+VSY_TVB+VSY_TVD)&&
xcnt>=(HSY_THS+HSY_THB)&&xcnt<(HSY_TEP+HSY_THB+HSY_THE))begin
valid<=1'b1;
end
else begin
valid<=1'b0;
end
end
//LCD驱动行场同步信号产生逻辑
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
lcd_hsy<=1'b1;
end
else if(xcnt==1'b0)begin
lcd_hsy<=1'b0;
end
else if(xcnt>=HSY_THS)begin
lcd_hsy<=1'b1;
end
else begin
lcd_hsy<=lcd_hsy;
end
end
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
lcd_vsy<=1'b1;
end
else if(ycnt==1'b0)begin
lcd_vsy<=1'b0;
end
else if(ycnt>=VSY_TVS)begin
lcd_vsy<=1'b1;
end
else begin
lcd_vsy<=lcd_vsy;
end
end
assign rom_ab = tmp_cnt+(ycnt-5'd18)*9'd100;
reg [8:0]tmp_cnt;
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
tmp_cnt<=1'b0;
end
else if(valid==1'b0)begin
tmp_cnt<=1'b0;
end
else if(xcnt>=(HSY_THS+HSY_THB)&&xcnt<(HSY_THS+HSY_THB+9'd100)&&dchange)begin
tmp_cnt<=tmp_cnt+1'b1;
end
else begin
tmp_cnt<=tmp_cnt;
end
end
reg [15:0]lcd_db_rgb;
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
lcd_db_rgb<=16'd0;
end
else if(ycnt>=(VSY_TVS+VSY_TVB)&&ycnt<(VSY_TVS+VSY_TVB+9'd100)
&&xcnt>=(HSY_THS+HSY_THB)&&xcnt<(HSY_THS+HSY_THB+9'd100))begin
if(dchange==1'b1)begin //图片区域
lcd_db_rgb<=rom_db;
end
else begin
lcd_db_rgb<=lcd_db_rgb;
end
end
else begin
lcd_db_rgb<=1'b0;
end
end
assign lcd_r =valid ? lcd_db_rgb[15:11]:5'd0;
assign lcd_g =valid ? lcd_db_rgb[10:5]:6'd0;
assign lcd_b =valid ? lcd_db_rgb[4:0]:5'd0;
endmodule
顶层文件:
module top(ext_clk_25m,ext_rst_n,lcd_light_en,lcd_clk,lcd_hsy,lcd_vsy,lcd_r,lcd_g,lcd_b
);
input ext_clk_25m;
input ext_rst_n;
output lcd_light_en;
output lcd_clk;
output lcd_hsy;
output lcd_vsy;
output [4:0] lcd_r;
output [5:0] lcd_g;
output [4:0] lcd_b;
wire [15:0] rom_db;
wire [13:0] rom_ab;
qvga_controller uut_qvga_controller(
.clk(ext_clk_25m),
.rst_n(ext_rst_n),
.lcd_light_en(lcd_light_en),
.lcd_clk(lcd_clk),
.lcd_hsy(lcd_hsy),
.lcd_vsy(lcd_vsy),
.lcd_r(lcd_r),
.lcd_g(lcd_g),
.lcd_b(lcd_b),
.rom_db(rom_db),
.rom_ab(rom_ab)
);
rom_img uut_rom_img(
.clka(ext_clk_25m), // input clka
.addra(rom_ab), // input [13 : 0] addra
.douta(rom_db) // output [15 : 0] douta
);
endmodule
显示测试:(板子的资源有限所以显示的像素不是很高)