折腾了几天,一直在研究如何在电脑上显示图片,总算在今天下午弄出来了,其实主要的问题是因为第一次学习怎样将图片的字库,存在FPGA的ROM中,以及怎样将它取出来显示在电脑,其他的和上两个实验的内容差不多,只要把上面几个问题想清楚了,这图片显示的不是很难的事!

//程序实现的功能:在电脑屏幕上显示一张64*64点阵的皮卡丘图片;
module vga_tp
       (
        clk,
        rst_n,
        hsync,
        vsync,
        vga_r,
        vga_g,
        vga_b
       
       );
       
input     clk;           //系统时钟50MHZ;
input     rst_n;         //复位信号,低电平有效;

output      hsync;       //列同步信号;
output      vsync;      //行同步信号;
output      vga_r;      //色彩信号;
output      vga_g;
output      vga_b;

  
reg[9:0] x_cnt;        //行坐标;
always @ (posedge clk or negedge rst_n)
  begin
         if(!rst_n)
            x_cnt<=10'd0;
         else if(x_cnt==10'd665)
            x_cnt<=10'd0;
         else if(y_cnt==11'd1039)
            x_cnt<=x_cnt+1'b1;
  end 

reg [10:0] y_cnt;       //列坐标;
always @(posedge clk or negedge rst_n)
  begin
         if(!rst_n)
            y_cnt<=11'd0;
         else if(y_cnt==1039)
            y_cnt<=11'd0;
         else  
            y_cnt<=y_cnt+1'b1;
  end

wire[9:0]   x_pos;         //有效显示区域坐标;
wire[10:0]  y_pos;

assign  x_pos=x_cnt-10'd31;        // 显示的初始位置,相当于坐标(0,0);
assign  y_pos=y_cnt-11'd187;      

wire valid;                //有效显示区;

assign   valid=((x_cnt>=10'd31)&&(x_cnt<10'd631)&&(y_cnt>=11'd187)&&(y_cnt<11'd987));  
  
            
                  
    

 reg vsync_r;             //行同步信号的产生;
always @ (posedge clk or negedge rst_n)
  begin
         if(!rst_n)
           vsync_r<=1'b1;
         else if(x_cnt==0)
           vsync_r<=1'b0;
         else if(x_cnt==6)
          vsync_r<=1'b1;
         else 
          vsync_r<=vsync_r; 
  end
assign  vsync=vsync_r;
 
reg hsync_r;             //列同步信号的产生;
always @ (posedge clk or negedge rst_n)
  begin
        if(!rst_n)
          hsync_r<=1'b1;
        else if(y_cnt==0)
          hsync_r<=1'b0;
        else if(y_cnt==120)
          hsync_r<=1'b1;
        else 
          hsync_r<=hsync_r;    
  end

assign  hsync=hsync_r;

wire [5:0] rom_addr;            //rom地址;
wire [63:0] rom_data;            //rom数据;

vga_zifu    vga_zifu_inst (
    .address ( rom_addr ),
    .clock ( clk ),
    .q ( rom_data )
    );
    
wire[9:0]x_pos_r;        //改变坐标的显示位置;
wire[10:0] y_pos_r;     

assign x_pos_r=x_pos-10'd250;     //将图片显示在电脑屏幕的中间位置;


assign y_pos_r=y_pos-11'd350;
    
reg[5:0] m;
always @ (posedge clk or negedge rst_n)
  begin
         if(!rst_n)
            m<=6'd0;
          else if(valid&&x_pos_r<64)
            m<=x_pos_r[5:0];            //m寄存器读取了当前行的地址(要在电脑上显示的行)
  end
  
reg[5:0] n;
always @ (posedge clk or negedge rst_n)
  begin
         if(!rst_n)
            n<=6'd0;
          else if(valid&&y_pos_r<64)
            n<=y_pos_r[5:0];           //n寄存器读取了当前列的地址(要在电脑上显示的列)
  end  

assign rom_addr=m;                    //将m赋给rom_addr;  n寄存器作为列,对rom读取的rom_data值,从高位到低位判断目前的第m行,第n列是点亮还是点灭;

assign vga_r=valid ? rom_data[6'd63-n]:1'd0;
         
assign vga_g=valid ? rom_data[6'd63-n]:1'd0;

assign vga_b=valid ? rom_data[6'd63-n]:1'd0 ; 
                
endmodule