如何使用verilog和VGA在fpga板上显示一些不同类型的图片

时间:2016-01-10 13:43:12

标签: verilog fpga

我正在尝试做我的学校的项目,我想要做的一项功能是在按下不同的按钮时显示不同类型的图片。据我所知,我已经在内存中加载了不同的图片。我现在正试图加载两张不同的图片并展示其中一张图片。然而,当我只尝试一张照片时它工作得很好但是当我尝试用两张照片时显示出来。真希望有人能帮帮我!以下是我的代码。

module top(
input clk,
input rst,
output [3:0] vgaRed,
output [3:0] vgaGreen,
output [3:0] vgaBlue,
output hsync,
output vsync
 );

wire [11:0] data;
wire clk_25MHz;
wire clk_22;
wire [16:0] pixel_addr;
wire [11:0] pixel;
wire valid;
wire [9:0] h_cnt; //640
wire [9:0] v_cnt;  //480
wire [11:0] data_1;
wire [16:0] pixel_addr_1;
wire [11:0] pixel_1;
wire valid_1;
wire [9:0] h_cnt_1; //640
wire [9:0] v_cnt_1;  //480

assign {vgaRed, vgaGreen, vgaBlue} = (valid==1'b1) ? pixel:12'h0;

 clock_divisor clk_wiz_0_inst(
  .clk(clk),
  .clk1(clk_25MHz),
  .clk22(clk_22)
);

mem_addr_gen mem_addr_gen_inst(
.clk(clk_22),
.rst(rst),
.h_cnt(h_cnt),
.v_cnt(v_cnt),
.pixel_addr(pixel_addr)
);


blk_mem_gen_0 blk_mem_gen_0_inst(
  .clka(clk_25MHz),
  .wea(0),
  .addra(pixel_addr),
  .dina(data[11:0]),
  .douta(pixel)
);


mem_addr_gen mem_addr_gen_inst_1(
    .clk(clk_22),
    .rst(rst),
    .h_cnt(h_cnt_1),
    .v_cnt(v_cnt_1),
    .pixel_addr(pixel_addr_1)
    );


    blk_mem_gen_1 blk_mem_gen_1_inst(
      .clka(clk_25MHz),
      .wea(0),
      .addra(pixel_addr_1),
      .dina(data_1[11:0]),
      .douta(pixel_1)
    ); 


vga_controller   vga_inst(
  .pclk(clk_25MHz),
  .reset(rst),
  .hsync(hsync),
  .vsync(vsync),
  .valid(valid),
  .h_cnt(h_cnt),
  .v_cnt(v_cnt)
);      
endmodule

由于它只能使用一张图片以正确的方式工作,我认为模块vga_controller,clock_divisor,mem_addr_gen和blk_mem_gen_0在模块的设计中不会出现问题,因此,我只发布详细信息我的顶级模块。谢谢!!

1 个答案:

答案 0 :(得分:0)

如果我正确理解您的代码,您的目的是为您要显示的每个图片实例化mem_addr_genblk_mem_gen。假设您的系统适用于单图像案例,那么这里有一些建议:

  1. 只要您的所有图片大小相同(显然为640x480),您可能只需要mem_addr_gen模块的一个实例 - 您应该能够共享h_cnt,{{1 {}}和v_cntpixel_addr' s。
  2. 的集合上
  3. 您需要一些方法从您的图像集中进行选择。
  4. 请考虑以下事项:

    blk_mem_gen

    这将分配任何图像"活动" (在这种情况下从0到7)到VGA。

    1. 最后,您想要一种方法来更改正在显示的图像。
    2. 这更依赖于您的实现,但作为示例:

      reg [2:0] activeImage; //between 0 and 7
      wire [11:0] pixel_out [7:0]; // pixel outputs from the blk_mem_gen
      wire [11:0] pixel;
      
      assign {vgaRed, vgaGreen, vgaBlue} = (valid==1'b1) ? pixel:12'h0;
      assign pixel = pixel_out[activeImage];
      
      blk_mem_gen_0 blk_mem_gen_0_inst(
        .clka(clk_25MHz),
        .wea(0),
        .addra(pixel_addr),
        .dina(data[11:0]),
        .douta(pixel_out[0])
      );
      ...
      

      在此代码中,每次按下按钮时,我们都会增加input button; input clk; input rst; reg buttonPrev; //previous button value reg [2:0] activeImage; //between 0 and 7 reg [2:0] nextImage; always@(posedge clk) begin buttonPrev <= button; if (rst) begin //reset activeImage <= 0; next_image <= 0; end else begin if (button && !buttonPrev) //button was just pressed nextImage <= nextImage + 1; if (h_cnt == 0 && v_cnt == 0) // starting a new frame activeImage <= nextImage; end end 一次(并按住按钮不会继续增加)。然后,当新框架开始时(nextImageh_cnt都为0),我们会将v_cnt更新为所需的activeImage。它仅在帧开始时更新,以避免在绘制图像的中途更改图像。