IP核使用
选择IP核
点击next之后可选择RAM/ROM,如果做图片显示推荐使用ROM
ADDRA表示地址,DOUTA为数据输出,CLKA为你的分频时钟。
选择位宽和深度
(建议:- 位宽不要太大,8,16,64之类的就可以了;
- 要显示的图片的分辨率不要太大, 200x200左右最好,太大IP核深度不一定够用
- 举例:如果一副200x200的图片,那就是40000个像素点,coe的位宽就可以设置为8位(保存每一个像素点的R,G,B,或者也可以声明为64位保存8个点的),深度是40000。而后在对应屏幕的x,y取出要显示的点的RGB即可)
初始化ROM/RAM的话可以用coe文件,Browse选择coe位置
图片生成coe文件
- coe文件格式
- Matlab代码示例
function Img2Coe(image)
% Use function [imread] to load pictrue to image
clc;
close all;
file = fopen('result.coe', 'w');
R = image(:,:,1);
R = floor(double(R) / 32);
G = image(:,:,2);
G = floor(double(G) / 32);
B = image(:,:,3);
B = floor(double(B) / 64);
[ROW,COL,COLOR] = size(image);
fprintf(file,'MEMORY_INITIALIZATION_RADIX=2;\nMEMORY_INITIALIZATION_VECTOR=\n');
for row = 1:ROW
for col = 1:COL
fprintf(file,dec2bin(R(row,col),3));
fprintf(file,dec2bin(G(row,col),3));
fprintf(file,dec2bin(B(row,col),2));
if row == ROW && col == COL
fprintf(file,';\n');
else
fprintf(file,',\n');
end
end
end
fclose(file);
newIm(:,:,1) = R;
newIm(:,:,2) = G;
newIm(:,:,3) = B;
imshow(newIm);
end
Verilog代码
- 顶层模块
module vga(input wire clk, rst,
output wire [2:0] r, g, output wire [1:0] b, output wire hs, vs
);
wire mclk;
wire ven;
wire [9:0] hc;
wire [9:0] vc;
//分频
clkdiv clock(
.clk(clk),
.clr(rst),
.mclk(mclk)
);
//生成VGA扫描信号
vgaSync syn(
.clk(mclk),
.rst(rst),
.hs(hs),
.vs(vs),
.videoen(ven),
.hc(hc),
.vc(vc)
);
//显示图像
vgaRGB rgb(
.hc(hc),
.vc(vc),
.videoen(ven),
.mclk(mclk),
.r(r),
.g(g),
.b(b)
);
endmodule
- 分频(Spartan6板系统时钟100MHZ,这里建议采用帧率60Hz,时序标准建议用640x480,对应分频为25MHZ)
module clkdiv(input wire clk, clr,
output wire mclk
);
reg [1:0]count = 0;
always @(posedge clk or posedge clr)
begin
if (clr)
count <= 0;
else
count <= count + 1'b1;
end
assign mclk = count[1];
endmodule
- 生成扫描信号
module vgaSync(input wire clk, rst,
output reg hs, vs, videoen, output reg [9:0]hc, vc
);
reg vsenable;
always @ (posedge clk)
begin
if(rst == 1)
hc <= 0;
else
begin
if(hc == 10'd799)
begin
hc <= 0;
vsenable <= 1;
end
else
begin
hc <= hc + 1'b1;
vsenable <= 0;
end
end
end
always @ (*)
begin
if(hc < 10'd96)
hs = 0;
else
hs = 1;
end
always @ (posedge clk)
begin
if(rst == 1)
vc <= 0;
else
if(vsenable == 1)
begin
if(vc == 10'd520)
vc <= 0;
else
vc <= vc + 1'b1;
end
end
always @ (*)
begin
if(vc < 2)
vs = 0;
else
vs = 1;
end
always @ (*)
begin
if((hc < 10'd784) && (hc >= 10'd144) && (vc < 10'd511) && (vc >= 10'd31))
videoen = 1;
else
videoen = 0;
end
endmodule
- 显示图片(以图片大小为200*200为例)
module vgaRGB(input wire [9:0]hc, vc, input wire videoen, mclk,
output reg [2:0] r, g, output reg [1:0] b
);
reg [15:0] addr = 0;
wire [7:0] data;
//ip核调用
ROM ROM0( .clka(mclk), .addra(addr), .douta(data) );
always @ (posedge mclk)
begin
if(videoen == 1)
begin
if(vc < 301 && vc > 100 && hc < 501 && hc > 300)
begin
//通过vc、hc计算出地址并获取图片对应位置RGB
addr <= (vc - 100 - 1) * 200 + (hc - 300) - 1;
r <= data[7:5];
g <= data[4:2];
b <= data[1:0];
end
else
begin
r <= 3'b111;
g <= 3'b111;
b <= 2'b111;
end
end
else
begin
r <= 0;
g <= 0;
b <= 0;
end
end
endmodule
- 接口绑定
NET "clk" LOC = "V10";
NET "rst" LOC = "C4";
NET "hs" LOC = "N6";
NET "vs" LOC = "P7";
NET "r[0]" LOC = "U7";
NET "r[1]" LOC = "V7";
NET "r[2]" LOC = "N7";
NET "g[0]" LOC = "P8";
NET "g[1]" LOC = "T6";
NET "g[2]" LOC = "V6";
NET "b[0]" LOC = "R7";
NET "b[1]" LOC = "T7";