Verilog VGA 静态显示图片

IP核使用

  • 选择IP核
    Verilog VGA 静态显示图片_第1张图片
    Verilog VGA 静态显示图片_第2张图片

  • 点击next之后可选择RAM/ROM,如果做图片显示推荐使用ROM
    Verilog VGA 静态显示图片_第3张图片

  • ADDRA表示地址,DOUTA为数据输出,CLKA为你的分频时钟。
    Verilog VGA 静态显示图片_第4张图片

  • 选择位宽和深度
    Verilog VGA 静态显示图片_第5张图片
    (建议:

    1. 位宽不要太大,8,16,64之类的就可以了;
    2. 要显示的图片的分辨率不要太大, 200x200左右最好,太大IP核深度不一定够用
    3. 举例:如果一副200x200的图片,那就是40000个像素点,coe的位宽就可以设置为8位(保存每一个像素点的R,G,B,或者也可以声明为64位保存8个点的),深度是40000。而后在对应屏幕的x,y取出要显示的点的RGB即可)
  • 初始化ROM/RAM的话可以用coe文件,Browse选择coe位置
    Verilog VGA 静态显示图片_第6张图片

图片生成coe文件

  • coe文件格式
    Verilog VGA 静态显示图片_第7张图片
  • 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";

你可能感兴趣的:(数字电路设计)